https://community.letsencrypt.org/t/when-choosing-an-elliptic-curve-look-for-a-safe-curve/161837
7.1.3.1.2 ECDSA The CA SHALL indicate an ECDSA key using the id‐ecPublicKey (OID: 1.2.840.10045.2.1) algorithm identifier. The parameters MUST use the namedCurve encoding.
For P‐256 keys, the namedCurve MUST be secp256r1 (OID: 1.2.840.10045.3.1.7). For P‐384 keys, the namedCurve MUST be secp384r1 (OID: 1.3.132.0.34). For P‐521 keys, the namedCurve MUST be secp521r1 (OID: 1.3.132.0.35). When encoded, the AlgorithmIdentifier for ECDSA keys MUST be byte‐for‐byte identical with the following hex‐encoded bytes: For P‐256 keys, 301306072a8648ce3d020106082a8648ce3d030107. For P‐384 keys, 301006072a8648ce3d020106052b81040022. For P‐521 keys, 301006072a8648ce3d020106052b81040023.
This isn't generally something that the average implementation developer has to consider. Choices are largely already made by standards and crypto libraries (and you really shouldn't write your own crypto library, unless you already know all these things by heart).
In a web context, ECDSA is generally only used with P-256 or P-384. Chrome doesn't even support anything else 116.
'use strict';
const crypto = require('crypto');
const fs = require('fs');
const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', { namedCurve: 'P-256' });
fs.writeFileSync('private.pem', privateKey.export({ type: 'pkcs8', format: 'pem' }));
fs.writeFileSync('public.pem', publicKey.export({ type: 'spki', format: 'pem' }));
const sign = crypto.createSign('SHA256');
sign.update('some data to sign');
sign.end();
// sign with the key read from remote
const signature = sign.sign(fs.readFileSync('private.pem'), 'base64');
const verify = crypto.createVerify('SHA256');
verify.update('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature, 'base64'));
const signature = sign.sign({
key: fs.readFileSync('private.pem'),
dsaEncoding: 'ieee-p1363',
}, 'base64');
const verify = crypto.createVerify('SHA256');
verify.update('some data to sign');
verify.end();
console.log(verify.verify({
key: publicKey,
dsaEncoding: 'ieee-p1363',
}, signature, 'base64'));
https://stackoverflow.com/a/39651457
The answer turns out to be that the Node crypto module generates ASN.1/DER signatures, while other APIs like jsrsasign and SubtleCrypto produce a “concatenated” signature. In both cases, the signature is a concatenation of (r, s). The difference is that ASN.1 does so with the minimum number of bytes, plus some payload length data; while the P1363 format uses two 32-bit hex encoded integers, zero-padding them if necessary.
https://stackoverflow.com/a/51179147
openssl ecparam -out ec_key.pem -name prime256v1 -genkey
openssl pkcs8 -topk8 -in ec_key.pem -out ec_key.pw.pem
The ec_key.key can be deleted but the private key will be password protected!
openssl ec -in ec_key.pw.pem -pubout -out ec_key.pub.pem