Closed CMCDragonkai closed 6 months ago
Ed25519
is not specified in WebCrypto API this is why algorithm names are different for native webcrypto and @peculiar/webcrypto
. For @peculiar/x509
it's possible to solve by extending EdAlgorithm. I'll prepare some examples and share them
I switched to using @peculiar/webcrypto
, but I'm wondering if there's ways of "constructing" or customising the webcrypto object in case I need to plug it with different underlying implementations like for mobile platforms or otherwise.
The Node.js implementation has since been updated to reflect the CFRG curves WICG draft.
I would suggest this polyfill to follow suit.
The draft is also partially supported in Deno. Chromium's implementation is ongoing and so is WebKit's.
@panva It sounds good. I've created the new ticket #60
Chromium's implementation is ongoing and so is WebKit's.
Chromium now supports Ed25519 algorithm, see https://blogs.igalia.com/jfernandez/2023/06/20/secure-curves-in-the-web-cryptography-api/.
Node.js crypto
implementation is indeed incompatible with Web Cryptography API implemenation, see https://github.com/paulmillr/noble-ed25519/discussions/98.
FWIW this is what I use to generate ED23319 keys using node
, deno
, and bun
https://github.com/guest271314/webbundle/blob/main/generateWebCryptoKeys.js:
import { writeFileSync } from "node:fs";
import { webcrypto } from "node:crypto";
const algorithm = { name: "Ed25519" };
const encoder = new TextEncoder();
const cryptoKey = await webcrypto.subtle.generateKey(
algorithm,
true, /* extractable */
["sign", "verify"],
);
const privateKey = JSON.stringify(
await webcrypto.subtle.exportKey("jwk", cryptoKey.privateKey),
);
writeFileSync("./privateKey.json", encoder.encode(privateKey));
const publicKey = JSON.stringify(
await webcrypto.subtle.exportKey("jwk", cryptoKey.publicKey),
);
writeFileSync("./publicKey.json", encoder.encode(publicKey));
Import private and public keys: https://github.com/guest271314/webbundle/blob/main/index.js#L11-L29
const privateKey = fs.readFileSync("./privateKey.json");
const publicKey = fs.readFileSync("./publicKey.json");
// https://github.com/tQsW/webcrypto-curve25519/blob/master/explainer.md
const cryptoKey = {
privateKey: await webcrypto.subtle.importKey(
"jwk",
JSON.parse(decoder.decode(privateKey)),
algorithm.name,
true,
["sign"],
),
publicKey: await webcrypto.subtle.importKey(
"jwk",
JSON.parse(decoder.decode(publicKey)),
algorithm.name,
true,
["verify"],
),
};
I've been using the https://github.com/PeculiarVentures/x509 library.
At first since webcrypto already available in nodejs, I thought it was sufficient to do this:
However subsequently I found that that there's an API difference between the way x509 expects Ed25519 algorithm objects that are based on this library, compared to the ones that in NodeJS (https://nodejs.org/api/webcrypto.html#ed25519ed448x25519x448-key-pairs).
For example in NodeJS's webcrypto, the
alg
parameter can just be:{ name: 'Ed25519' }
.However for peculiar's webcrypto, the
alg
parameter has to be{ name: 'EdDSA', namedCurve: 'Ed25519' }
.This caused some incompatibilities in
webcrypto.subtle.importKey
and inx509.X509CertificateGenerator.createSelfSigned
In the case of the
importKey
, I have to use a webcrypto's expected alg parameter:During the generation of the certificate, if I used node's webcrypto, the certificate generation works without exceptions, however I notice that the
signatureAlgorithm
field is empty, and stays as:The resulting certificate when output to PEM is not readable by
openssl x509 -in ./tmp/cert -text
.So it seems that if I want to use ed25519 with https://github.com/PeculiarVentures/x509, I have to use peculiar's webcrypto and not node's webcrypto.