Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Specify ECDSA curves #6904

Closed
max-mapper opened this issue Jan 18, 2014 · 11 comments
Closed

Specify ECDSA curves #6904

max-mapper opened this issue Jan 18, 2014 · 11 comments
Assignees

Comments

@max-mapper
Copy link

It would be nice to get the ability to specify a curve with OpenSSL's EC_KEY_new_by_curve_name API when signing using require('crypto').createHash('ecdsa-with-SHA1')

The PR that added ECDH support to TLS used this API (erikdubbelboer@1b4395b#lib-tls-js-P4)

@max-mapper
Copy link
Author

I think it can be done with the EVP_PKEY_set1_EC_KEY method in OpenSSL. In JS maybe a second argument to createHash, e.g. require('crypto').createHash(algorithm, namedCurve)

@ghost ghost assigned indutny Jan 18, 2014
@indutny
Copy link
Member

indutny commented Jan 18, 2014

Btw, you probably meant createSign, because ecdsa is a signing algorithm. Right?

@indutny
Copy link
Member

indutny commented Jan 18, 2014

This should be done with EVP_PKEY_CTX_set_ec_paramgen_curve_nid on mdctx.

@indutny
Copy link
Member

indutny commented Jan 19, 2014

Btw, are you completely sure that this is required and doesn't work now? I've just parsed one EC private key with asn1.js and that's what I got:

{ version: 1,
  privateKey: <Buffer 5c 42 f2 bb 09 2a 47 4b e2 54 1b 08 b1 55 21 36 a5 37 74 c8 a1 2f f6 64 f4 5a 21 27 be 6a 01 18>,
  parameters: { type: 'namedCurve', value: [ 1, 2, 840, 10045, 3, 1, 7 ] },
  publicKey:
   { unused: 0,
     data: <Buffer 04 f6 21 89 6e bf f1 82 b0 dc 4c fa e8 9d f2 d6 4a 0f a2 aa df a2 6c c7 ca be 6d 30 55 ce 96 a8 39 f6 93 9e 4f 39 18 89 29 7d 09 7a 75 05 8c 8a 71 ff 58 ...> } }

The source was:

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFxC8rsJKkdL4lQbCLFVITalN3TIoS/2ZPRaISe+agEYoAoGCCqGSM49
AwEHoUQDQgAE9iGJbr/xgrDcTPronfLWSg+iqt+ibMfKvm0wVc6WqDn2k55PORiJ
KX0JenUFjIpx/1j8vrOKOjIPbwd1w4TBng==
-----END EC PRIVATE KEY-----

Where namedCurve represents:

secp256r1 OBJECT IDENTIFIER ::= {
    iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
    prime(1) 7 }

which is another name for prime256v1, which was what I specified when generating key:

./out/Release/openssl-cli ecparam -name prime256v1 -genkey

So, as a conclusion, I think that this info should be already known to the OpenSSL. And there should be no need to specify it separately.

@indutny
Copy link
Member

indutny commented Jan 19, 2014

Here are asn1.js grammar, just in case:

var EVPrivateKey = asn1.define('ECPrivateKey', function() {
  this.seq().obj(
    this.key('version').int(),
    this.key('privateKey').octstr(),
    this.key('parameters').optional().explicit(0).use(ECParameters),
    this.key('publicKey').optional().explicit(1).bitstr()
  );
});

var ECParameters = asn1.define('ECParameters', function() {
  this.choice({
    namedCurve: this.objid()
  });
});

@indutny
Copy link
Member

indutny commented Jan 19, 2014

And the relevant: http://tools.ietf.org/html/rfc5915

@indutny
Copy link
Member

indutny commented Jan 20, 2014

A confirmation that it is working:

var crypto = require('crypto');

var keys = {
  priv: '-----BEGIN EC PRIVATE KEY-----\n' +
        'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' +
        'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' +
        'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
        '-----END EC PRIVATE KEY-----\n',
  pub: '-----BEGIN PUBLIC KEY-----\n' +
       'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNh\n' +
       'B8i3mXyIMq704m2m52FdfKZ2pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' +
       '-----END PUBLIC KEY-----\n'
};

var data = new Buffer('hello');

var sign = crypto.createSign('ecdsa-with-SHA1');
sign.update(data);
var signature = sign.sign(keys.priv);

console.log(signature);

var verify = crypto.createVerify('ecdsa-with-SHA1');
verify.update(data);
console.log(verify.verify(keys.pub, signature));

@shea256
Copy link

shea256 commented Sep 9, 2015

This is slightly off topic but is there a list of types of verifiers that can be created by crypto.createVerify? I want to do crypto.createVerify('ecdsa-with-SHA256') but I'm not having any luck. And the documentation (https://nodejs.org/api/crypto.html#crypto_crypto_createverify_algorithm) is pretty sparse.

@bnoordhuis
Copy link
Member

@shea256 I think crypto.getHashes() is what you want?

@shea256
Copy link

shea256 commented Sep 18, 2015

Thank you @bnoordhuis. Unfortunately it seems as if there is no 'ecdsa-with-SHA256' as there should be with the new OpenSSL.

@indutny are you aware of any way to do ECDSA message signing with SHA256 via the crypto library?

P.S. I've been working with your elliptic.js library in parallel and just submitted an issue there.

@ismaelbej
Copy link

Looking at the node source (node_crypto.cc, función Sign::SignInit) the parameter for createSign is passed to the openssl function EVP_get_digestbyname. The ecdsa signature algorithm seems to be implicit with the private key oid.

This code works (I didn't test with others keys or other curves)

var sign = crypto.createSign('sha256');
sign.update(data);
var signature = sign.sign(keys.priv);
var verify = crypto.createVerify('sha256');
verify.update(data);
verified = verify.verify(keys.pub, signature)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants