I'm working on doing WebAuthN on the server, and I'm running this in Node:
import nCrypto from "crypto";
const base64UrlToUintArray = (src) => {
const raw = atob(src.replaceAll("-", "+").replaceAll("_", "/"));
return Uint8Array.from(raw, (char) => char.charCodeAt(0));
};
const jwk = {
kty: "EC",
alg: "ES256",
crv: "P-256",
x: "uymD4lAdTz26QJV30-DRkEt1d9WTazEKPfuWN3Fyd9U",
y: "BZvD93pXLYfqXkp9sqylz_UN88OLapiV8drZQHdUCZE",
};
const input = Uint8Array.from([
177, 105, 230, 129, 73, 100, 147, 50, 55, 183, 116, 206, 222, 74, 197, 72,
177, 173, 14, 226, 46, 148, 229, 253, 77, 144, 96, 248, 233, 108, 69, 171, 5,
101, 81, 31, 94, 138, 188, 129, 159, 72, 206, 19, 189, 169, 103, 118, 178, 17,
79, 84, 126, 190, 133, 144, 77, 172, 161, 115, 67, 100, 154, 222, 235, 62, 5,
6, 187,
]);
const signature =
"MEQCIAE8ZT7CC9uQFaOIzPaEtLwnIGgjJLDYeZTyOc9hzxmkAiAphf71sZD5zxfAu0ELOOcn6yAfzu-Jbm-XT3SLe9dQgw";
const key = await nCrypto.subtle.importKey(
"jwk",
jwk,
{ name: "ECDSA", namedCurve: "P-256" },
false,
["verify"]
);
const verified = await nCrypto.subtle.verify(
{
name: "ECDSA",
hash: "SHA-256",
},
key,
base64UrlToUintArray(signature),
input
);
const verified2 = nCrypto
.createVerify("sha256")
.update(Buffer.from(input))
.verify(
nCrypto.createPublicKey({ key: jwk, format: "jwk" }),
Buffer.from(base64UrlToUintArray(signature))
);
console.log("web crypto verification", verified);
console.log("node crypto verification", verified2);
The Node implementation returns true as it should be, but the Web Crypto implementation returns false. How do I fix this?
* I want to use Web Crypto because eventually this will run on a serverless platform, my dev server is node-based though
I converted it to R-S format with this code: