0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -05:00

fix(ext/crypto): export private x25519 JWK key (#27828)

Ref https://github.com/denoland/deno/issues/26431
This commit is contained in:
Divy Srivastava 2025-01-27 22:25:00 +05:30 committed by GitHub
parent 21e8260cc9
commit 88490d0927
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 42 additions and 27 deletions

View file

@ -48,6 +48,7 @@ import {
op_crypto_verify_ed25519,
op_crypto_verify_key,
op_crypto_wrap_key,
op_crypto_x25519_public_key,
} from "ext:core/ops";
const {
ArrayBufferIsView,
@ -4532,17 +4533,18 @@ function exportKeyX25519(format, key, innerKey) {
return TypedArrayPrototypeGetBuffer(pkcs8Der);
}
case "jwk": {
if (key[_type] === "private") {
throw new DOMException("Not implemented", "NotSupportedError");
}
const x = op_crypto_base64url_encode(innerKey);
const jwk = {
kty: "OKP",
crv: "X25519",
x,
"key_ops": key.usages,
ext: key[_extractable],
};
if (key[_type] === "private") {
jwk.x = op_crypto_x25519_public_key(innerKey);
jwk.d = op_crypto_base64url_encode(innerKey);
} else {
jwk.x = op_crypto_base64url_encode(innerKey);
}
return jwk;
}
default:

View file

@ -98,6 +98,7 @@ deno_core::extension!(deno_crypto,
op_crypto_base64url_decode,
op_crypto_base64url_encode,
x25519::op_crypto_generate_x25519_keypair,
x25519::op_crypto_x25519_public_key,
x25519::op_crypto_derive_bits_x25519,
x25519::op_crypto_import_spki_x25519,
x25519::op_crypto_import_pkcs8_x25519,

View file

@ -1,5 +1,6 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
use curve25519_dalek::montgomery::MontgomeryPoint;
use deno_core::op2;
use deno_core::ToJsBuffer;
@ -20,17 +21,16 @@ pub enum X25519Error {
#[error(transparent)]
Der(#[from] spki::der::Error),
}
// u-coordinate of the base point.
const X25519_BASEPOINT_BYTES: [u8; 32] = [
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
];
#[op2(fast)]
pub fn op_crypto_generate_x25519_keypair(
#[buffer] pkey: &mut [u8],
#[buffer] pubkey: &mut [u8],
) {
// u-coordinate of the base point.
const X25519_BASEPOINT_BYTES: [u8; 32] = [
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
];
let mut rng = OsRng;
rng.fill_bytes(pkey);
// https://www.rfc-editor.org/rfc/rfc7748#section-6.1
@ -42,6 +42,17 @@ pub fn op_crypto_generate_x25519_keypair(
pubkey.copy_from_slice(&x25519_dalek::x25519(pkey, X25519_BASEPOINT_BYTES));
}
#[op2]
#[string]
pub fn op_crypto_x25519_public_key(#[buffer] private_key: &[u8]) -> String {
use base64::Engine;
let private_key: [u8; 32] =
private_key.try_into().expect("Expected byteLength 32");
BASE64_URL_SAFE_NO_PAD
.encode(x25519_dalek::x25519(private_key, X25519_BASEPOINT_BYTES))
}
const MONTGOMERY_IDENTITY: MontgomeryPoint = MontgomeryPoint([0; 32]);
#[op2(fast)]

View file

@ -2085,3 +2085,20 @@ Deno.test(async function x25519SharedSecret() {
assertEquals(sharedSecret1.byteLength, 16);
assertEquals(new Uint8Array(sharedSecret1), new Uint8Array(sharedSecret2));
});
Deno.test(async function x25519ExportJwk() {
const keyPair = await crypto.subtle.generateKey(
{
name: "X25519",
},
true,
["deriveBits"],
) as CryptoKeyPair;
const jwk = await crypto.subtle.exportKey("jwk", keyPair.privateKey);
assertEquals(jwk.kty, "OKP");
assertEquals(jwk.crv, "X25519");
assert(jwk.d);
assert(jwk.x);
});

View file

@ -845,14 +845,6 @@
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, false, [sign])",
"Good parameters: Ed448 bits (pkcs8, buffer(73), {name: Ed448}, false, [sign, sign])",
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, false, [sign, sign])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits, deriveKey])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits, deriveKey])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
"Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
@ -902,14 +894,6 @@
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, false, [sign])",
"Good parameters: Ed448 bits (pkcs8, buffer(73), {name: Ed448}, false, [sign, sign])",
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, false, [sign, sign])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits, deriveKey])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits, deriveKey])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
"Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",