Closed symbiont-aurelien-bonnel closed 4 years ago
You are right. The difference is in the encoding format. OpenSSL uses ASN1 format for ECC signature.
@peculiar/webcrypto module is based on nodejs crypto and implements this transform
https://github.com/PeculiarVentures/webcrypto/blob/master/src/mechs/ec/crypto.ts#L53-L74
@microshine to be clear the format returned by this package is consistent with webcrypto correct?
@peculiar/webcrypto
returns ECC signature in WebCrypto format
One more convertation example of DER to WebCrypto format https://github.com/PeculiarVentures/node-webcrypto-ossl/blob/master/src/ec/ec_dsa.cpp#L88
Thanks. So by design.
Maybe we can incorporate a converter for people in the p11 package to make it easy like we have in other libraries.
@rmhrisk That would be nice and I think would greatly increase the usability of this library.
@microshine thanks for sharing the conversion example.
I added and published webcrypto-core@next
module which includes ASN1 schemas for EC and RSA objects.
npm install webcrypto-core@next
const { AsnSerializer } = require("@peculiar/asn1-schema");
const core = require("webcrypto-core");
const { Crypto } = require("@peculiar/webcrypto");
const nodeCrypto = require("crypto");
async function main() {
const crypto = new Crypto();
const alg = {
name: "ECDSA",
namedCurve: "P-521",
hash: "SHA-256"
}
const data = Buffer.from("Hello");
// Generate ECDSA key and sign data
const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]);
const signature = await crypto.subtle.sign(alg, keys.privateKey, data);
console.log("WebCrypto Signature:", Buffer.from(signature).toString("hex"));
// Convert WebCrypto signature to DER
const derSignature = core.asn1.EcDsaSignature.fromWebCryptoSignature(signature);
const der = AsnSerializer.serialize(derSignature);
console.log("DER Signature:", Buffer.from(der).toString("hex"));
// nodejs
// Convert WebCrypto Key to PEM
const pkcs8 = await crypto.subtle.exportKey("pkcs8", keys.publicKey);
const publicKey = core.PemConverter.fromBufferSource(pkcs8, "public key");
// Verify signature using NodeJS crypto
const cryptoAlg = alg.hash.replace("-", "");
const signer = nodeCrypto.createVerify(cryptoAlg);
signer.update(data);
const options = {
key: publicKey,
};
const ok = signer.verify(options, Buffer.from(der));
console.log("Valid:", ok);
}
main().catch(e => console.error(e));
WebCrypto Signature: 012cec66df15709a95f2cd878af36951762727d3ebe5f9cae96dd45931f66205cad49945cc96a7ae13be0615c8eb2447023161a3de574d2b59847440e8bed1c6124400911e3907efe07bc57b37c4df41b36390e263485610921d75b50f76db01c6bcd7c1d4b0e93f1fee7886bfd7eb9963ad0f4a0db927b5ac06b8da9073771dfbd4a856
DER Signature: 3081880242012cec66df15709a95f2cd878af36951762727d3ebe5f9cae96dd45931f66205cad49945cc96a7ae13be0615c8eb2447023161a3de574d2b59847440e8bed1c61244024200911e3907efe07bc57b37c4df41b36390e263485610921d75b50f76db01c6bcd7c1d4b0e93f1fee7886bfd7eb9963ad0f4a0db927b5ac06b8da9073771dfbd4a856
Valid: true
@symbiont-aurelien-bonnel Please test this code. If it works then I'll publish a new version of webcrypto-core
P.S. It must work for all WebCrypto implementations
Thanks, I went the long way and used directly the asn1-schema functions to handle padding and serialize to asn1, works well. I can confirm this works too.
Thank you for the quick updates and the great work!
I published webcrpyto-core@1.0.19
I am producing a signature using this library interacting with a Yubikey 5. That signature is verifiable using this package's
crypto.subtle.verify
function properly.I am trying to get the built-in nodejs crypto verifier to also verify the signature - to no avail. As I understand it, the signature is not in openssl (asn1) format and therefore cannot be verified correctly. What transforms can be used to make the signature produced verifiable by the built-in crypto library/openssl?
Code below:
node-webcrypto-p11 signing & verifying - PASS
node-webcrypt-p11 signing & nodejs crypto verifying - FAIL
Thanks