Code Monkey home page Code Monkey logo

elliptic's Introduction

Elliptic Build Status Coverage Status Code Climate

Saucelabs Test Status

Fast elliptic-curve cryptography in a plain javascript implementation.

NOTE: Please take a look at http://safecurves.cr.yp.to/ before choosing a curve for your cryptography operations.

Incentive

ECC is much slower than regular RSA cryptography, the JS implementations are even more slower.

Benchmarks

$ node benchmarks/index.js
Benchmarking: sign
elliptic#sign x 262 ops/sec ±0.51% (177 runs sampled)
eccjs#sign x 55.91 ops/sec ±0.90% (144 runs sampled)
------------------------
Fastest is elliptic#sign
========================
Benchmarking: verify
elliptic#verify x 113 ops/sec ±0.50% (166 runs sampled)
eccjs#verify x 48.56 ops/sec ±0.36% (125 runs sampled)
------------------------
Fastest is elliptic#verify
========================
Benchmarking: gen
elliptic#gen x 294 ops/sec ±0.43% (176 runs sampled)
eccjs#gen x 62.25 ops/sec ±0.63% (129 runs sampled)
------------------------
Fastest is elliptic#gen
========================
Benchmarking: ecdh
elliptic#ecdh x 136 ops/sec ±0.85% (156 runs sampled)
------------------------
Fastest is elliptic#ecdh
========================

API

ECDSA

var EC = require('elliptic').ec;

// Create and initialize EC context
// (better do it once and reuse it)
var ec = new EC('secp256k1');

// Generate keys
var key = ec.genKeyPair();

// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash);

// Export DER encoded signature in Array
var derSign = signature.toDER();

// Verify signature
console.log(key.verify(msgHash, derSign));

// CHECK WITH NO PRIVATE KEY

var pubPoint = key.getPublic();
var x = pubPoint.getX();
var y = pubPoint.getY();

// Public Key MUST be either:
// 1) '04' + hex string of x + hex string of y; or
// 2) object with two hex string properties (x and y); or
// 3) object with two buffer properties (x and y)
var pub = pubPoint.encode('hex');                                 // case 1
var pub = { x: x.toString('hex'), y: y.toString('hex') };         // case 2
var pub = { x: x.toBuffer(), y: y.toBuffer() };                   // case 3
var pub = { x: x.toArrayLike(Buffer), y: y.toArrayLike(Buffer) }; // case 3

// Import public key
var key = ec.keyFromPublic(pub, 'hex');

// Signature MUST be either:
// 1) DER-encoded signature as hex-string; or
// 2) DER-encoded signature as buffer; or
// 3) object with two hex-string properties (r and s); or
// 4) object with two buffer properties (r and s)

var signature = '3046022100...'; // case 1
var signature = new Buffer('...'); // case 2
var signature = { r: 'b1fc...', s: '9c42...' }; // case 3

// Verify signature
console.log(key.verify(msgHash, signature));

EdDSA

var EdDSA = require('elliptic').eddsa;

// Create and initialize EdDSA context
// (better do it once and reuse it)
var ec = new EdDSA('ed25519');

// Create key pair from secret
var key = ec.keyFromSecret('693e3c...'); // hex string, array or Buffer

// Sign the message's hash (input must be an array, or a hex-string)
var msgHash = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var signature = key.sign(msgHash).toHex();

// Verify signature
console.log(key.verify(msgHash, signature));

// CHECK WITH NO PRIVATE KEY

// Import public key
var pub = '0a1af638...';
var key = ec.keyFromPublic(pub, 'hex');

// Verify signature
var signature = '70bed1...';
console.log(key.verify(msgHash, signature));

ECDH

var EC = require('elliptic').ec;
var ec = new EC('curve25519');

// Generate keys
var key1 = ec.genKeyPair();
var key2 = ec.genKeyPair();

var shared1 = key1.derive(key2.getPublic());
var shared2 = key2.derive(key1.getPublic());

console.log('Both shared secrets are BN instances');
console.log(shared1.toString(16));
console.log(shared2.toString(16));

three and more members:

var EC = require('elliptic').ec;
var ec = new EC('curve25519');

var A = ec.genKeyPair();
var B = ec.genKeyPair();
var C = ec.genKeyPair();

var AB = A.getPublic().mul(B.getPrivate())
var BC = B.getPublic().mul(C.getPrivate())
var CA = C.getPublic().mul(A.getPrivate())

var ABC = AB.mul(C.getPrivate())
var BCA = BC.mul(A.getPrivate())
var CAB = CA.mul(B.getPrivate())

console.log(ABC.getX().toString(16))
console.log(BCA.getX().toString(16))
console.log(CAB.getX().toString(16))

NOTE: .derive() returns a BN instance.

Supported curves

Elliptic.js support following curve types:

  • Short Weierstrass
  • Montgomery
  • Edwards
  • Twisted Edwards

Following curve 'presets' are embedded into the library:

  • secp256k1
  • p192
  • p224
  • p256
  • p384
  • p521
  • curve25519
  • ed25519

NOTE: That curve25519 could not be used for ECDSA, use ed25519 instead.

Implementation details

ECDSA is using deterministic k value generation as per RFC6979. Most of the curve operations are performed on non-affine coordinates (either projective or extended), various windowing techniques are used for different cases.

All operations are performed in reduction context using bn.js, hashing is provided by hash.js

Related projects

  • eccrypto: isomorphic implementation of ECDSA, ECDH and ECIES for both browserify and node (uses elliptic for browser and secp256k1-node for node)

LICENSE

This software is licensed under the MIT License.

Copyright Fedor Indutny, 2014.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

elliptic's People

Contributors

alexeykudinkin avatar benediamond avatar bolzon avatar calvinmetcalf avatar dependabot[bot] avatar dlakata avatar eordano avatar evilaliv3 avatar fanatid avatar gnarula avatar guybedford avatar hege91 avatar indutny avatar kagami avatar kdenhartog avatar ljharb avatar lovato avatar oberien avatar ryanxcharles avatar sublimator avatar tigerbot avatar trysound avatar xg-wang avatar zbuc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elliptic's Issues

Compatibility with openssl/spongycastle

I'm having some trouble verifying ECDSA signatures generated by elliptic with other libraries and vice-versa (eg, signature generated in JS and verified on a different device). How much testing is there against other implementations?

Example:
Using prime256v1
Private Key:'74864f3a6af4da4ad93d23d36ddf63f61ba4f42c33acb3ab78ce614010aa7ae2'
Public Key:'04d0769514776c9f0601435e79e0a1b5e59128a8cd0502f8700e4a2517eb0361b013bb80e18e385495ad1718b1b0ec5c7628e978889ec68a5edb13f2e9e17ce8ff'
Data Signed:"Hello" ==> '48656c6c6f'

Signature generated by spongycastle (verifies with openssl): MEYCIQDPG+N2MqTtE7pcNHt7FO3okJz7JFKyAo0mlQpJ3wV5KAIhANggvkc7Ev8imFj8CympKVj4+hTnZsNMLhPG9L+l+Cfc

Signature generated by elliptic (verification with openssl fails):
MEUCIQCQVQ27xIXUsK/h27DvbOzIUDXNttYAHf9A9HkvxdS0dQIgI98rJSQPfjZBrO7qfgzjFpQ/q1JUK1KqATkzw6snQmA=

The signature generation code using elliptic is as follows:


var key = ec.keyPair(privKey, 'hex');
var sig = key.sign(msg);


privKey is passed in as a string "74864f3a6af4da4ad93d23d36ddf63f61ba4f42c33acb3ab78ce614010aa7ae2"

Maybe there's something wrong in my code, if you know any things to watch out for, please share.

Thanks!

Point encoding

function compressedPoint(p) {
  const x = p.getX().toArray();
  const y = p.getY();
  while (x.length < 32) x.unshift(0)
  return [y.isEven() ? 0x02 : 0x03].concat(x);
}

Currently for implementing some seed -> secret routines (the algorithm is set in stone) which involves hashing byte representations of points, I needed a little utility function. I note the only code for this currently in elliptic is in the EC/KeyPair#getPublic method and not immediately useful.

Maybe some Point.encode(encoding) / curve.decodePoint(encoding) methods? Shrug?

Check for empty message

Should the sign function check msg for empty string/array somewhere in this place?
Signature of empty message (z = 0) could be trivially forged per [1], [2].

Endormorphism optimization bias

Was just reading through some posts around the net, and I found this comment by @gmaxwell on hackernews.
The comment (which is just under a year old):

(2) Some unusual curves can have an optimization which common implementations might take which results in biased nonces. These curves are not widely used on the Internet. I'm doubtful you've ever heard of them (except Bitcoin's curve, which is a GLV curve, but I'm relatively confident no one is using the endomorphism in signing). They also give advice on avoiding that weakness.

It hints at a bias, though I'm not 100% on the intricacies (at this time).

Just figured I'd ping you @indutny, the paper is at https://www.irisa.fr/celtique/zapalowicz/papers/asiacrypt2014.pdf

Happy to see this closed if this is a non-issue.

ed25519 ECDH encryption?

When selecting the ed25519 curve like this:

var ec = new ellipticjs.ec('ed25519');

Can it then be used for asymmetric encryption?

I have searched the web with mixed results. Some say something about the possibilities to convert the keys between ed25519 and curve25519? But no clear indication as to using ed25519 directly?

When tested with the library it seam to work fine, but I do not know about security etc.

Benny

Strange import error

I'm getting "Cannot read property version of undefined" on the first line of this block:

elliptic.version = require('../package.json').version; // required var is undefined
elliptic.utils = require('./elliptic/utils'); // required var is correct
elliptic.rand = require('brorand'); // required var is correct

on browserify bundle. If I comment this line, everything works ok (including other elliptic imports!).
Can you shed the light on what may cause this error?
Should I post this issue to browserify?

Providing ecies_key_derivation request

Is there anyway to plugin in a ECDH_compute_key method here:

https://github.com/indutny/elliptic/blob/master/test/ecdh-test.js

The openssl call ECDH_compute_key lets you put in a call back called ecies_key_derivation. I need to somehow plug in that I would like to use a SHA512 hash in the key derivation (derive) method.

I think with a simple modification this could be done. Can you please confirm? I want to know I'm on the right track.

More information here: http://stackoverflow.com/questions/26595085/computing-a-ecdh-shared-secret-in-javascript

Thank you...

Lib does not work currently in MS Windows browsers

On all MS browser platforms where I have tested it, the lib load stops at line 2830 because the browser does not support window.crypto.GetRandomValues. Have tested it with Windows phone 8.1 and the default browser of Windows 8.1.
You need an alternative approch.

RNG is not provably secure?

Apparently your RNG is not as provably secure as the one in SJCL as you appear to rely on the built in browser RNG, which might be compromised.

https://github.com/indutny/elliptic/blob/master/lib/elliptic/rand.js

Some RNGs in operating systems as well as the RNG instruction in CPUs are throught to be potentially compromised.

Note a copy of this comment also appears at the SJCL issue where I learned of the existence of your project.

bitwiseshiftleft/sjcl#168 (comment)

Signing method returns the same signature every time (for a given key and message)

Here's the code I'm using:

var EC = require('elliptic').ec,
    secp256k1 = new EC('secp256k1'),
    sigFormatter = require('ecdsa-sig-formatter')

var privateKeyHex = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229',
    publicKeyHex = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69',
    privateKeyObject = secp256k1.keyFromPrivate(privateKeyHex, 'hex'),
    publicKeyObject = secp256k1.keyFromPublic(publicKeyHex, 'hex')

var messageString = 'Hello, World',
    messageBuffer = new Buffer(messageString),
    messageBytes = messageBuffer.toJSON().data

var derSignatureObject = privateKeyObject.sign(messageBytes),
    derSignatureArray = derSignatureObject.toDER(),
    derSignatureBuffer = new Buffer(derSignatureArray),
    joseSignature = sigFormatter.derToJose(derSignatureBuffer, 'ES256')

console.log(derSignatureObject)

var verified = publicKeyObject.verify(messageBytes, derSignatureBuffer)

console.log(verified)

Is there some issue with the method or am I doing something wrong?

Thank you!

QUESTION: use with webcrypto

let's say i'm using webcryptography in the browser and have some code like this:

    var payload = {}
    var combo = JSON.stringify({ ... })

    var ab2b = function (ab) {
        var buffer = []
        var view = new Uint8Array(ab)

        for (var i = 0; i < ab.byteLength; i++) buffer[i] = view[i]
        return buffer
    }

    var s2ab = function (s) {
        var buffer = new Uint8Array(s.length)

        for (var i = 0; i < s.length; i++) buffer[i] = s.charCodeAt(i)
        return buffer
    }

    var to_hex = function (bs) {
        var encoded = []

        for (var i = 0; i < bs.length; i++) {
            encoded.push('0123456789abcdef'[(bs[i] >> 4) & 15])
            encoded.push('0123456789abcdef'[bs[i] & 15])
        }
        return encoded.join('')
    }

    window.crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' },
                                     true, [ 'sign', 'verify' ]).then(function (pair) {
        window.crypto.subtle.exportKey('raw', pair.publicKey).then(function (publicKey) {
            window.crypto.subtle.sign({ name: 'ECDSA', hash: { name: 'SHA-256' } },
                                      pair.privateKey, s2ab(combo)).then(function(signature) {
                payload.publicKey = to_hex(ab2b(publickKey)
                payload.signature = to_hex(ab2b(signature)
            })
        })
    })

what i am trying to figure out is how to take the two values in payload that contain hex-encoded strings and invoke key.verify() appropriately:

    var elliptic = require('elliptic').ec
    var ec = new elliptic('secp256k1')
    var options = { r: payload.signature.substr(0, 64), s: payload.signature.substr(64, 64) }

    var key = ec.keyFromPublic(payload.publicKey, 'hex')
    console.log(key.verify(combo, options, key, 'hex')

can you advise me as to how i should be calling KeyFromPublic and verify?

thanks!

/mtr

cc: @diracdeltas

Store and restore keys

The best approach to store and restore keys are not clear to me. How will you recommend to store and restore keys, curves etc.

Like to json stringify and store the values in a database as a string value.

As far as I see it also the curve and parameters are stored in the key's ec variable.

To store shall I just store values from getPublic and getPrivate and on restore I initialise like this:

var ec = new ellipticjs.ec([curve selected]);
var key = ec.genKeyPair();
key._importPrivate([stored getPrivate key string]);
key._importPublic([stored getPublic key string]);

Error: Signature without r or s

I want to verify a message.
I have the message, signature and public key, but no private key.

When verifying the message, I get the error: Signature without r or s

Public key format is: '04' + X + Y
Signature format is: R + S
Both in hex.

Am I doing something wrong or is this a bug?

My code:

var msg = '...'; // hidden
var pubKey = '04e6f90994768e51c2834879841542992494b9030e1b765e766f8b60a56213fb9f91903ee24f6baaaaf6afbce3adcfbc4362c1e1e21218ed3f1be6317908db3323';
var signature = 'b32911bfd9f88ae4a0c337df2c0f254d2232a162b85ce3019c2ae7cb1f56f06b525b4813557ace1e6f2f2080e77dd49ecec49d030a4fa23854880e696e941344';

var ecdsa = new elliptic.ec('p256');
var res = ecdsa.verify(msg, signature, pubKey, 'hex'); // throws exception

I've tried to use the ec/Signature class to load this, but no success too.

Thanks.

Q: What is the correct way to load an ECDSA secret key?

Hi, I've just got a question for you that I'd like to ask now while I'm reading through source code and experimenting a little bit.

I'd like to sign some message using the p384 curve and a secret key I have been provided for testing purposes. The key is being given to me in Base64-DER-encoded format. It was produced with the following Python code, which uses a python-ecdsa library:

def generate_ecdsa_pubkey(key_file_name, secret_key_dir='.'):
    sk = SigningKey.generate(curve=NIST384p)
    vk = sk.get_verifying_key()
    f = open(os.sep.join([secret_key_dir, key_file_name]), 'w')
    f.write(base64.standard_b64encode(sk.to_der()))
    f.close()
    return base64.standard_b64encode(vk.to_der())

Please note that this is not a security critical scenario- these keys and the signatures produced with them are only being used for local testing and will not be used in production.

Am I correct in thinking that I can obtain a key which will be capable of signing a buffer of data using the following?

const EC = require('elliptic').ec
const ec = new EC('p384')
const key = ec.keyFromPrivate(new Buffer(loadedSecretKeyString), 64)
const signature = key.sign(new Buffer(stringMessage))

Could there perhaps be some documentation written in the repository to properly explain how to load keys from files, to ease use of this library by other developers in the future?

Thanks!

Restored keys no longer works

Hi

After upgrade to version 3.0.3 my old example code no longer work (also my main product)

Old Issue: #7

When I have restored the private and public key from compact hex and try to get a shared secret it fails with error:

Cannot read property 'clone' of null in Chrome or num is null in FF

Do it like this:

// Recreate the same keys/points as with key1
var key3 = ec2.keyPair(key1private, 'hex');
var key4 = ec2.keyPair(key1public, 'hex');

The error seam to be here:

// ECDH
KeyPair.prototype.derive = function derive(pub) {
  return pub.mul(this.priv).getX();
};

it seam as if getX is no longer defined ???????

NB: Run directly in browser

Problem: Elliptic.js use in client browser

Hi Fedor

Have a problem as I like to include your library "elliptic.js" into my hobby project https://pcrypt.org/dev.

(long reason why I like to do this, but I like to implement some new functionality)

The file elliptic.js has been included in the header

When i try to use the library as taken from your example:

var ec = new EC('secp256k1');

var key1 = ec.genKeyPair();
var key2 = ec.genKeyPair();

var shared1 = key1.derive(key2.getPublic());
var shared2 = key2.derive(key1.getPublic());

console.log('Both shared secrets are BN instances');
console.log(shared1.toString(16));
console.log(shared2.toString(16));

The browser complain with the following message:

Uncaught ReferenceError: EC is not defined

in the first line of the code.

What am I doing wrong? You may have an easy solution before I start to dive into this problem or test a lot of other libraries. And it may also be that this will help others.

Looks like almost all ecc libraries are node.js oriented and not browser friendly.

NB: You can see the problem live here: https://pcrypt.org/dev/ecc.php

Best regards
Benny

sign interprets message as hex even when it's not hex

The toArray function strips non-hex characters without warning. If a user tries to pass a UTF8 string as the message, they may assume that it is signing the string message and not realize that the message is being interpreted as hex with non-hex characters stripped. It would be more defensive to throw an exception here:

https://github.com/indutny/elliptic/blob/master/lib/elliptic/utils.js#L33
https://github.com/indutny/elliptic/blob/master/lib/elliptic/utils.js#L164

What does '04' in public key means?

I noticed that when I do key.getPublic('hex') it gets prefixed with 0x04 byte. I also found that i can do key.getPublic(true, 'hex') to get 'compressed' version, which will not include 0x04 byte.

What 0x04 byte means?

wrong recoveryParam

Working on secp256k1-node v2.x I found that sometimes sign return wrong recoveryParam...

var assert = require('assert')
var randomBytes = require('crypto').randomBytes
var EC = require('elliptic').ec

var ec = new EC('secp256k1')
while (true) {
  var msg = randomBytes(32)
  var priv = randomBytes(32)
  var pubHex = ec.keyFromPrivate(priv).getPublic().encodeCompressed('hex')
  var sig = ec.sign(msg, priv, {canonical: true})
  console.log('signature recovery param:', sig.recoveryParam)
  var pubHex2 = ec.recoverPubKey(msg, sig, sig.recoveryParam).encodeCompressed('hex')

  sig.recoveryParam = null
  var recid = ec.getKeyRecoveryParam(msg, sig, ec.keyFromPrivate(priv).getPublic())
  console.log('signature recovery param (restored):', recid)

  assert.equal(pubHex, pubHex2)
}

Saving EC Private Key to PEM

This is a follow up to #43. I was looking to solve the same problem but I am not able to successfully read the private key generated with asn1.js using openssl. The public key works fine. Can you tell what I'm doing wrong?

save keys

function save_keys() {
    /*
     Create a secp256k1 key and write the pub and private bits to disk in pem.
    */
    var EC = require('elliptic').ec;
    var fs = require('fs');
    var asn = require("asn1.js");

    var ec = new EC('secp256k1');
    var keyPair = ec.genKeyPair();

    var CURVE = [1, 3, 132, 0, 10] // :secp256k1

    var ECPublicKey = asn.define("PublicKey", function() {
      this.seq().obj(
        this.key("algorithm").seq().obj(
          this.key("id").objid(),
          this.key("curve").objid()
        ),
        this.key("pub").bitstr()
      );
    });

    var ECPrivateKey = asn.define("ECPrivateKey", function() {
      this.seq().obj(
        this.key('version').int().def(1),
        this.key('privateKey').octstr(),
        this.key('parameters').explicit(0).objid().optional(),
        this.key('publicKey').explicit(1).bitstr().optional()
      );
    });

    var pem = ECPublicKey.encode({
      algorithm: {
        // :id-ecPublicKey
        id: [1, 2, 840, 10045, 2, 1],
        curve: CURVE,
      },
      pub: {
        unused: 0,
        data: new Buffer(keyPair.getPublic("array")),
      },
    }, "pem", {label: "PUBLIC KEY"});
    fs.writeFileSync("myPublicKey.pem", pem + "\n");

    var pem = ECPrivateKey.encode({
      version: 1,
      parameters: CURVE,
      publicKey: {data: new Buffer(keyPair.getPublic("array"))},
      privateKey: new Buffer(keyPair.getPrivate().toArray())
    }, "pem", {label: "EC PRIVATE KEY"});
    fs.writeFileSync("myPrivateKey.pem", pem + "\n");
}
save_keys()

The structure of the private key looks correct.

openssl asn1parse -in myPrivateKey.pem
    0:d=0  hl=2 l= 113 cons: SEQUENCE
    2:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:A400891535A816B9E8ABE662E8A9042067061F0D096686C079541A9160A3FF0F
   36:d=1  hl=2 l=   7 cons: cont [ 0 ]
   38:d=2  hl=2 l=   5 prim: OBJECT            :secp256k1
   45:d=1  hl=2 l=  68 cons: cont [ 1 ]
   47:d=2  hl=2 l=  66 prim: BIT STRING

but loading the key fails.

openssl ec -in myPrivateKey.pem -text -noout
read EC key
unable to load Key
22991:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:/SourceCache/OpenSSL098/OpenSSL098-52.10.1/src/crypto/asn1/tasn_dec.c:1315:
22991:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-52.10.1/src/crypto/asn1/tasn_dec.c:827:
22991:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-52.10.1/src/crypto/asn1/tasn_dec.c:747:Field=version, Type=EC_PRIVATEKEY
22991:error:10092010:elliptic curve routines:d2i_ECPrivateKey:EC lib:/SourceCache/OpenSSL098/OpenSSL098-52.10.1/src/crypto/ec/ec_asn1.c:1116:
22991:error:0D09A00D:asn1 encoding routines:d2i_PrivateKey:ASN1 lib:/SourceCache/OpenSSL098/OpenSSL098-52.10.1/src/crypto/asn1/d2i_pr.c:119:
22991:error:0907B00D:PEM routines:PEM_READ_BIO_PRIVATEKEY:ASN1 lib:/SourceCache/OpenSSL098/OpenSSL098-52.10.1/src/crypto/pem/pem_pkey.c:125:

DER parser failing to parse r and s values

Not sure what to make of this. I was using bcoin to verify the entire blockchain when elliptic threw when verifying this transaction. I figure this is a nonstandard DER signature that elliptic cannot parse for whatever reason.

var data = {
  msg: 'de17556d2111ef6a964c9c136054870495b005b3942ad7b62628af00293b9aa8',
  sig: '3045022100a9379b66c22432585cb2f5e1e85736c69cf5fdc9e1033ad583fc27f0b7c561d802202c7b5d9d92ceca742829ffbe28ba6565faa8f94556cb091cbc39d2f11d45946700',
  key: '04650a9a1deb523f636379ec70c29b3e1e832e314dea0f791160f3dba628f4f509360e525318bf7892af9ffe2f585bf7b264aa31792744ec1885ce17f3b1ef50f3'
};

require('elliptic').ec('secp256k1').verify(data.msg, data.sig, data.key, 'hex');

Original error:

Error: Signature without r or s
    at assert (/home/chjj/work/node_modules/bcoin/node_modules/elliptic/lib/elliptic/utils.js:8:11)
    at new Signature (/home/chjj/work/node_modules/bcoin/node_modules/elliptic/lib/elliptic/ec/signature.js:16:3)
    at EC.verify (/home/chjj/work/node_modules/bcoin/node_modules/elliptic/lib/elliptic/ec/index.js:153:15)
    at Object.checksig (/home/chjj/work/node_modules/bcoin/lib/bcoin/script.js:310:24)
    at Object.execute (/home/chjj/work/node_modules/bcoin/lib/bcoin/script.js:841:22)
    at Object.verify (/home/chjj/work/node_modules/bcoin/lib/bcoin/script.js:217:16)
    at TX.<anonymous> (/home/chjj/work/node_modules/bcoin/lib/bcoin/tx.js:925:25)
    at Array.every (native)
    at TX.verify (/home/chjj/work/node_modules/bcoin/lib/bcoin/tx.js:916:22)
    at /home/chjj/work/node_modules/bcoin/lib/bcoin/chain.js:685:17

Private key generation sha256 trouble

I'm using sha-256.js to generate hashsum for creating private key with ec.keyFromPrivate. When I'm trying to get private value back the value differs:

var ec = new EC('ed25519');

var hash = Sha256.hash('12345678'); // -> ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f

var key = ec.keyFromPrivate(hash, 'hex');
key.getPrivate('hex'); // -> 0f797c8118f02dfb649607dd5d3f8c74fed2e26f1cb2bf73f85af36693270f59

The same result on chrome and nodejs. Nodejs crypto module generates the same hash as Sha256. Package ed25519-native return correct private key value.

another newbie question

i am transitioning some code from https://github.com/thejh/node-curve25519 to this package. as mentioned in an earlier issue, this is the curve25519-donna algorithm, which is described here: http://cr.yp.to/ecdh.html

what i am seeing is that the same inputs for the local private key and the remote public are producing different values. this leads me to believe that i am using the API in this package incorrectly (since i know that the other package produces good values with this input, and I'm confident that this package will produce good values if invoked correctly).

% node donna.js
               my private key =843b75caa5bdb940f740b7d9262e2ae9937c946dca7b0d18617ff5a1a33f46

    old pkg says my public key=200b85ac0e08d3fd0a0be90436765119037d30b7bff56f07cfab51ec1691837f
    new pkg says my public key=098aac55eae1f4c026fe443614ef450e9d7a4d2ac740ad67c9ff84ff41aab70f

  old pkg says your public key=97b22cf64c25ae2db61d07618ff291086feff2ae8779e57be59e988c33916b0f
  new pkg says your public key=17b22cf64c25ae2db61d07618ff291086feff2ae8779e57be59e988c33916b22

old pkg says the shared secret=91bae78939e897c5996417c77c5e3e19f82f4143acb34ef23848d3b6cc1f9930
new pkg says the shared secret=2a8fef7deb2436b8877fc8302e05eb9884099bc289fc8419de9f43c450c7c603

the source file is here https://gist.github.com/mrose17/36a9f5ada76bfab4b8bc

could you "clue me up" as to what i'm doing wrong here? many thanks!

elliptic.version broken with browserify

The line elliptic.version = require('../package.json').version; throws an error with require('../package.json') coming up as undefined for me, and I'm not sure why. I was able to manually change the line to elliptic.version = '1.0.1';, and everything worked fine again. This only seemed to be a problem when using watchify.

Not sure what else would be useful for this bug report - I'm using node v0.12, browserify, transforms reactify and brfs with {globals: true} for brfs.

Different S in elliptic and secp256k1

Hi.
That's probably not an issue with elliptic but maybe you will give a hint or some help.

I compare signatures for the same message and private key generated with elliptic and secp256k1-node. Sometimes I get the same result (output in DER format), sometimes not.

Example code:

#!/usr/bin/env node

var crypto = require("crypto");
var secp256k1 = require("secp256k1");
var EC = require("elliptic").ec;

var ec = new EC("secp256k1");
var privateKey = new Buffer(32);
privateKey.fill(1);
var publicKey = secp256k1.createPublicKey(privateKey);

function signWithSecp256k1(msg) {
  return secp256k1.sign(privateKey, msg);
}

function verifyWithSecp256k1(msg, sig) {
  return secp256k1.verify(publicKey, msg, sig) === 1;
}

function signWithElliptic(msg) {
  return new Buffer(ec.sign(msg, privateKey).toDER());
}

function verifyWithElliptic(msg, sig) {
  return ec.verify(msg, sig, publicKey);
}

function start() {
  var msg = process.argv[2];
  if (!msg) {
    console.log("No message provided");
    process.exit(1);
  }
  msg = crypto.createHash("sha256").update(msg).digest();
  console.log("Message:", msg.toString("hex"));

  var sigFromSecp256k1 = signWithSecp256k1(msg);
  var hsigFromSecp256k1 = sigFromSecp256k1.toString("hex");
  var sigFromElliptic = signWithElliptic(msg);
  var hsigFromElliptic = sigFromElliptic.toString("hex");

  console.log("Signature from secp256k1:", hsigFromSecp256k1);
  console.log("Signature from elliptic:", hsigFromElliptic);
  console.log(
    "\nSignatures are",
    hsigFromSecp256k1 === hsigFromElliptic ? "equal" : "NON equal");

  var verified = (
      verifyWithSecp256k1(msg, sigFromSecp256k1) &&
      verifyWithSecp256k1(msg, sigFromElliptic) &&
      verifyWithElliptic(msg, sigFromSecp256k1) &&
      verifyWithElliptic(msg, sigFromElliptic));
  console.log("Verify is", verified ? "ok" : "NOT ok");
}

start();

Output:

$ ./1.js 1
Message: 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b
@@@ k: 1e2a72fa3c78004111a6cabc6984f71e33aac85d04b2cdb621632fcf352a76e6
@@@ k: 1e2a72fa3c78004111a6cabc6984f71e33aac85d04b2cdb621632fcf352a76e6
Signature from secp256k1: 304402201009b15ce8943b846fb3d3bdc47c50ead4ad4da98f588935c0df5cd117069c24022026bcb6dc37d21ede4873941cfb8d744badc312d5c24750b9b00cd7901e9687b6
Signature from elliptic: 304402201009b15ce8943b846fb3d3bdc47c50ead4ad4da98f588935c0df5cd117069c24022026bcb6dc37d21ede4873941cfb8d744badc312d5c24750b9b00cd7901e9687b6

Signatures are equal
Verify is ok
$ ./1.js 12
Message: 6b51d431df5d7f141cbececcf79edf3dd861c3b4069f0b11661a3eefacbba918
@@@ k: 26c9d570e5558bb38fcd7c8960347fffdf4e04d884fc039f98b47318b931fc4e
@@@ k: 26c9d570e5558bb38fcd7c8960347fffdf4e04d884fc039f98b47318b931fc4e
Signature from secp256k1: 3044022062b919656b48d771948a04f77e2acb750eb0ae4aaa77e9d4e7a5b04160f5836c02203e1fcf65916209c0f15189bf727793729ed527ddbd31a3237c08a25f8714108d
Signature from elliptic: 3044022062b919656b48d771948a04f77e2acb750eb0ae4aaa77e9d4e7a5b04160f5836c02203e1fcf65916209c0f15189bf727793729ed527ddbd31a3237c08a25f8714108d

Signatures are equal
Verify is ok
$ ./1.js 123
Message: a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
@@@ k: cd00933e1156db3a772853dca9abd5cd38760e31b6388edb0d0c58394f9c9a16
@@@ k: cd00933e1156db3a772853dca9abd5cd38760e31b6388edb0d0c58394f9c9a16
Signature from secp256k1: 3045022100b15edd98a0e296327a9350837fa8d8e8744802e0e2fad8db63882265ba5bd5ee0220115ce8dcbae2c66d929a9b4fb54f479fbadb99ed733fe56ecc0324aa9e65eaf4
Signature from elliptic: 3046022100b15edd98a0e296327a9350837fa8d8e8744802e0e2fad8db63882265ba5bd5ee022100eea31723451d39926d6564b04ab0b85effd342f93c08baccf3cf39e231d0564d

Signatures are NON equal
Verify is ok
$ ./1.js 1234
Message: 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4
@@@ k: f9f2b01c16b8f37b637676743fd0262ee1bbacc4b8108b95e5c34cc3a7e496c7
@@@ k: f9f2b01c16b8f37b637676743fd0262ee1bbacc4b8108b95e5c34cc3a7e496c7
Signature from secp256k1: 304402206f5a5383a059039d1c7f1bfe260797296845285e99a7ca192ec6fa2135d58a1c02200ebd17c140715c51e3b708f474a0b9a59e094b85d10542257efd01bbc810a527
Signature from elliptic: 304402206f5a5383a059039d1c7f1bfe260797296845285e99a7ca192ec6fa2135d58a1c02200ebd17c140715c51e3b708f474a0b9a59e094b85d10542257efd01bbc810a527

Signatures are equal
Verify is ok

(I also added k output for both implementations.)

So, curves are the same, keys are the same, messages are the same, k are the same, R are the same and sometimes S are not the same. Verifycation is passed everytime for all 4 variants (secp256k1 against two sigs and elliptic against two sigs).

Do you have any ideas why this might happen? Thanks.

point multiplication produces incorrect public key in rare situations

var EC = require('elliptic').ec
var ec = new EC('secp256k1')

var point = ec.g.mul('f2cc9d2b008927db94b89e04e2f6e70c180e547b3e5e564b06b8215d1c264b53')
// <EC Point x: 495f99aa21d7e60ff3f065f2a14e67612b29b1cb5af7b7fc4738cede6f2d9eba y: 41a2d4539b40a914e755a3a24367ce731195c354480dad4f2ce9e9c8f8003bce>

var point1 = ec.curve.pointFromX(true, '495f99aa21d7e60ff3f065f2a14e67612b29b1cb5af7b7fc4738cede6f2d9eba')
// <EC Point x: 495f99aa21d7e60ff3f065f2a14e67612b29b1cb5af7b7fc4738cede6f2d9eba y: 3dc9318f0a7ae59bafbccef98692931dc6a8c28208333e88de5c031766f70777>

var point2 = ec.curve.pointFromX(false, '495f99aa21d7e60ff3f065f2a14e67612b29b1cb5af7b7fc4738cede6f2d9eba')
// <EC Point x: 495f99aa21d7e60ff3f065f2a14e67612b29b1cb5af7b7fc4738cede6f2d9eba y: c236ce70f5851a6450433106796d6ce239573d7df7ccc17721a3fce79908f4b8>

var keypair = ec.keyPair('f2cc9d2b008927db94b89e04e2f6e70c180e547b3e5e564b06b8215d1c264b53')
// <Key priv: f2cc9d2b008927db94b89e04e2f6e70c180e547b3e5e564b06b8215d1c264b53 pub: null >

var pub = keypair.getPublic(true, 'hex')
// produces incorrect pub: '02495f99aa21d7e60ff3f065f2a14e67612b29b1cb5af7b7fc4738cede6f2d9eba'

// correct values:
// pubkey: "03e275faa35bd1e88f5df6e8f9f6edb93bdf1d65f4915efc79fd7a726ec0c21700"
// address: "19FKem9YKbszEwsXRLw9WnkggMQrdLbAhE"
// wif: "L5MgSwNB2R76xBGorofRSTuQFd1bm3hQMFVf3u2CneFom8u1Yt7G"

Related: bitpay/bitcore#894

make the library smaller, or break it up

I'd really like to use the library to implement the Edwards e521 curve on my own PassLok app (also on GitHub), which is currently using SJCL. People are suspicious about the NIST curves, which are what SJCL supports. Now, what's holding me from using elliptic.js is its sheer size. 180 kiloBytes!

Maybe you can break it up into smaller chunks, so I only need to add the components that really get used?

Thanks!

Google Closure Support

I've been trying to do browser cryptography with ClojureScript, which leans on the Google Closure compiler for dead code removal. I've been using BitPay's BitAuth, which has elliptic as an upstream dependency (albeit version 1.0.0 according to their package.json).

I've been having some issues with the Google Closure compiler and elliptic, has this been resolved in later versions?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.