PeculiarVentures / webcrypto

A WebCrypto Polyfill for NodeJS
MIT License
185 stars 23 forks source link

ECDSA signature variations #42

Closed hollowaysmith closed 2 years ago

hollowaysmith commented 2 years ago

Does this library have this problem?

https://stackoverflow.com/questions/39554165/ecdsa-signatures-between-node-js-and-webcrypto-appear-to-be-incompatible

I seem to be having problems verifying data+signature in the browser, using keys generated by this library. When I generate the keys in the browser it works fine, so is there a mismatch in ecdsa?

microshine commented 2 years ago

Please try that script (NodeJS 16). It works fine for me.

This script allows to use the same ECDSA keys for @pecluliar/webcrypto and NodeJS WebCrypto API. It verifies signatures which were created in one provider by another.

const assert = require("assert");
const { webcrypto } = require("crypto");
const { Crypto } = require("@peculiar/webcrypto");

const nCrypto = webcrypto;
const pCrypto = new Crypto();

async function main() {
  const alg = {
    name: "ECDSA",
    namedCurve: "P-256",
    hash: "SHA-256"
  };
  const data = pCrypto.getRandomValues(new Uint8Array(100));

  const iterations = 100;

  let i = iterations;
  while (i--) {
    const pKeys = await pCrypto.subtle.generateKey(alg, true, ["sign", "verify"]);
    const pkcs8 = await pCrypto.subtle.exportKey("pkcs8", pKeys.privateKey);
    const spki = await pCrypto.subtle.exportKey("spki", pKeys.publicKey);

    const nKeys = {
      privateKey: await nCrypto.subtle.importKey("pkcs8", pkcs8, alg, false, ["sign"]),
      publicKey: await nCrypto.subtle.importKey("spki", spki, alg, true, ["verify"]),
    };

    const pSignature = await pCrypto.subtle.sign(alg, pKeys.privateKey, data);
    const nSignature = await nCrypto.subtle.sign(alg, nKeys.privateKey, data);

    // Verify NodeJS WebCrypto signature using @peculiar/webcrypto
    const pOk = await pCrypto.subtle.verify(alg, pKeys.publicKey, nSignature, data);
    // Verify @peculiar/webcrypto signature using NodeJS WebCrypto provider
    const nOk = await nCrypto.subtle.verify(alg, nKeys.publicKey, pSignature, data);
    assert.ok(pOk);
    assert.ok(nOk);
  }
}

main()
  .catch(e => console.error(e));
microshine commented 2 years ago

Also @peculiar/webcrypto uses test vectors created in the browser.

If you've got any examples of keys and signatures that throw the exception please share them

hollowaysmith commented 2 years ago

Apologies. I think I made a mistake forgetting to put namedCurve: "P-256" when signing and it works now. Thanks