mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
feat(ext/crypto): add x25519 and Ed25519 CFRG curves (#14119)
This commit is contained in:
parent
f3dd13730c
commit
f02f2425d5
8 changed files with 1184 additions and 155 deletions
158
Cargo.lock
generated
158
Cargo.lock
generated
|
@ -25,7 +25,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -68,7 +68,7 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.7",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -304,7 +304,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -313,7 +313,7 @@ version = "0.10.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -328,7 +328,7 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a90ec2df9600c28a01c56c4784c9207a96d2451833aeceb8cc97e4c9548bb78"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -624,8 +624,8 @@ version = "0.4.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f2b443d17d49dad5ef0ede301c3179cc923b8822f3393b4d2c28c269dd4a122"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"generic-array 0.14.6",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
@ -636,8 +636,8 @@ version = "0.1.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"generic-array 0.14.6",
|
||||
"rand_core 0.6.4",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
|
@ -688,6 +688,32 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"digest 0.8.1",
|
||||
"rand_core 0.5.1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"digest 0.9.0",
|
||||
"rand_core 0.5.1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
version = "0.5.0"
|
||||
|
@ -955,6 +981,7 @@ dependencies = [
|
|||
"cbc",
|
||||
"const-oid",
|
||||
"ctr",
|
||||
"curve25519-dalek 2.1.3",
|
||||
"deno_core",
|
||||
"deno_web",
|
||||
"elliptic-curve",
|
||||
|
@ -973,6 +1000,7 @@ dependencies = [
|
|||
"spki",
|
||||
"tokio",
|
||||
"uuid",
|
||||
"x25519-dalek",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1335,13 +1363,22 @@ version = "0.1.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1519,12 +1556,12 @@ dependencies = [
|
|||
"der",
|
||||
"digest 0.10.5",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
"group",
|
||||
"hkdf",
|
||||
"pem-rfc7468",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
|
@ -1697,7 +1734,7 @@ version = "0.12.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df689201f395c6b90dfe87127685f8dbfc083a5e779e613575d8bd7314300c3e"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
|
@ -1931,6 +1968,15 @@ dependencies = [
|
|||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
|
@ -1941,6 +1987,17 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
|
@ -1949,7 +2006,7 @@ checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2043,7 +2100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7391856def869c1c81063a03457c676fbcd419709c3dfb33d8d319de484b154d"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
|
@ -2333,7 +2390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2774,7 +2831,7 @@ checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"log 0.4.17",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
|
@ -3428,7 +3485,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3438,7 +3495,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3447,7 +3513,7 @@ version = "0.6.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3627,7 +3693,7 @@ dependencies = [
|
|||
"num-traits",
|
||||
"pkcs1",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"smallvec",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
|
@ -3821,7 +3887,7 @@ checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
|
|||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
|
@ -4006,7 +4072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "deb766570a2825fa972bceff0d195727876a9cdf2460ab2e52d455dc2de47fd9"
|
||||
dependencies = [
|
||||
"digest 0.10.5",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4617,6 +4683,18 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.43",
|
||||
"quote 1.0.21",
|
||||
"syn 1.0.99",
|
||||
"unicode-xid 0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-info"
|
||||
version = "0.9.1"
|
||||
|
@ -5308,7 +5386,7 @@ version = "1.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.7",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -5364,6 +5442,12 @@ dependencies = [
|
|||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -5671,6 +5755,17 @@ dependencies = [
|
|||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x25519-dalek"
|
||||
version = "2.0.0-pre.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df"
|
||||
dependencies = [
|
||||
"curve25519-dalek 3.2.0",
|
||||
"rand_core 0.6.4",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "0.2.3"
|
||||
|
@ -5717,6 +5812,21 @@ name = "zeroize"
|
|||
version = "1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.43",
|
||||
"quote 1.0.21",
|
||||
"syn 1.0.99",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
|
|
22
cli/bench/secure_curves.js
Normal file
22
cli/bench/secure_curves.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
? Deno.args
|
||||
: [process.argv[2], process.argv[3]];
|
||||
|
||||
total = total ? parseInt(total, 0) : 50;
|
||||
count = count ? parseInt(count, 10) : 10000;
|
||||
|
||||
async function bench(fun) {
|
||||
const start = Date.now();
|
||||
for (let i = 0; i < count; i++) await fun();
|
||||
const elapsed = Date.now() - start;
|
||||
const rate = Math.floor(count / (elapsed / 1000));
|
||||
console.log(`time ${elapsed} ms rate ${rate}`);
|
||||
if (--total) await bench(fun);
|
||||
}
|
||||
|
||||
const { subtle } = typeof crypto !== "undefined"
|
||||
? crypto
|
||||
: require("crypto").webcrypto;
|
||||
|
||||
bench(() => subtle.generateKey("X25519", true, ["deriveKey"]));
|
|
@ -98,18 +98,22 @@
|
|||
"AES-GCM": "AesKeyGenParams",
|
||||
"AES-KW": "AesKeyGenParams",
|
||||
"HMAC": "HmacKeyGenParams",
|
||||
"X25519": null,
|
||||
"Ed25519": null,
|
||||
},
|
||||
"sign": {
|
||||
"RSASSA-PKCS1-v1_5": null,
|
||||
"RSA-PSS": "RsaPssParams",
|
||||
"ECDSA": "EcdsaParams",
|
||||
"HMAC": null,
|
||||
"Ed25519": null,
|
||||
},
|
||||
"verify": {
|
||||
"RSASSA-PKCS1-v1_5": null,
|
||||
"RSA-PSS": "RsaPssParams",
|
||||
"ECDSA": "EcdsaParams",
|
||||
"HMAC": null,
|
||||
"Ed25519": null,
|
||||
},
|
||||
"importKey": {
|
||||
"RSASSA-PKCS1-v1_5": "RsaHashedImportParams",
|
||||
|
@ -124,11 +128,13 @@
|
|||
"AES-CBC": null,
|
||||
"AES-GCM": null,
|
||||
"AES-KW": null,
|
||||
"X25519": null,
|
||||
},
|
||||
"deriveBits": {
|
||||
"HKDF": "HkdfParams",
|
||||
"PBKDF2": "Pbkdf2Params",
|
||||
"ECDH": "EcdhKeyDeriveParams",
|
||||
"X25519": "EcdhKeyDeriveParams",
|
||||
},
|
||||
"encrypt": {
|
||||
"RSA-OAEP": "RsaOaepParams",
|
||||
|
@ -834,6 +840,26 @@
|
|||
|
||||
return signature.buffer;
|
||||
}
|
||||
case "Ed25519": {
|
||||
// 1.
|
||||
if (key[_type] !== "private") {
|
||||
throw new DOMException(
|
||||
"Key type not supported",
|
||||
"InvalidAccessError",
|
||||
);
|
||||
}
|
||||
|
||||
// https://briansmith.org/rustdoc/src/ring/ec/curve25519/ed25519/signing.rs.html#260
|
||||
const SIGNATURE_LEN = 32 * 2; // ELEM_LEN + SCALAR_LEN
|
||||
const signature = new Uint8Array(SIGNATURE_LEN);
|
||||
if (!ops.op_sign_ed25519(keyData, data, signature)) {
|
||||
throw new DOMException(
|
||||
"Failed to sign",
|
||||
"OperationError",
|
||||
);
|
||||
}
|
||||
return signature.buffer;
|
||||
}
|
||||
}
|
||||
|
||||
throw new TypeError("unreachable");
|
||||
|
@ -955,6 +981,22 @@
|
|||
["wrapKey", "unwrapKey"],
|
||||
);
|
||||
}
|
||||
case "X25519": {
|
||||
return importKeyX25519(
|
||||
format,
|
||||
keyData,
|
||||
extractable,
|
||||
keyUsages,
|
||||
);
|
||||
}
|
||||
case "Ed25519": {
|
||||
return importKeyEd25519(
|
||||
format,
|
||||
keyData,
|
||||
extractable,
|
||||
keyUsages,
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new DOMException("Not implemented", "NotSupportedError");
|
||||
}
|
||||
|
@ -1003,6 +1045,10 @@
|
|||
result = exportKeyEC(format, key, innerKey);
|
||||
break;
|
||||
}
|
||||
case "Ed25519": {
|
||||
result = exportKeyEd25519(format, key, innerKey);
|
||||
break;
|
||||
}
|
||||
case "AES-CTR":
|
||||
case "AES-CBC":
|
||||
case "AES-GCM":
|
||||
|
@ -1283,6 +1329,17 @@
|
|||
namedCurve: key[_algorithm].namedCurve,
|
||||
}, data);
|
||||
}
|
||||
case "Ed25519": {
|
||||
// 1.
|
||||
if (key[_type] !== "public") {
|
||||
throw new DOMException(
|
||||
"Key type not supported",
|
||||
"InvalidAccessError",
|
||||
);
|
||||
}
|
||||
|
||||
return ops.op_verify_ed25519(keyData, data, signature);
|
||||
}
|
||||
}
|
||||
|
||||
throw new TypeError("unreachable");
|
||||
|
@ -1611,7 +1668,6 @@
|
|||
const usages = keyUsages;
|
||||
|
||||
const normalizedAlgorithm = normalizeAlgorithm(algorithm, "generateKey");
|
||||
|
||||
const result = await generateKey(
|
||||
normalizedAlgorithm,
|
||||
extractable,
|
||||
|
@ -1910,6 +1966,95 @@
|
|||
|
||||
return generateKeyAES(normalizedAlgorithm, extractable, usages);
|
||||
}
|
||||
case "X25519": {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
usages,
|
||||
(u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
const privateKeyData = new Uint8Array(32);
|
||||
const publicKeyData = new Uint8Array(32);
|
||||
ops.op_generate_x25519_keypair(privateKeyData, publicKeyData);
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
|
||||
|
||||
const publicHandle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: algorithmName,
|
||||
};
|
||||
|
||||
const publicKey = constructKey(
|
||||
"public",
|
||||
true,
|
||||
usageIntersection(usages, []),
|
||||
algorithm,
|
||||
publicHandle,
|
||||
);
|
||||
|
||||
const privateKey = constructKey(
|
||||
"private",
|
||||
extractable,
|
||||
usageIntersection(usages, ["deriveKey", "deriveBits"]),
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
|
||||
return { publicKey, privateKey };
|
||||
}
|
||||
case "Ed25519": {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
usages,
|
||||
(u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const ED25519_SEED_LEN = 32;
|
||||
const ED25519_PUBLIC_KEY_LEN = 32;
|
||||
const privateKeyData = new Uint8Array(ED25519_SEED_LEN);
|
||||
const publicKeyData = new Uint8Array(ED25519_PUBLIC_KEY_LEN);
|
||||
if (
|
||||
!ops.op_generate_ed25519_keypair(privateKeyData, publicKeyData)
|
||||
) {
|
||||
throw new DOMException("Failed to generate key", "OperationError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
|
||||
|
||||
const publicHandle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: algorithmName,
|
||||
};
|
||||
|
||||
const publicKey = constructKey(
|
||||
"public",
|
||||
true,
|
||||
usageIntersection(usages, ["verify"]),
|
||||
algorithm,
|
||||
publicHandle,
|
||||
);
|
||||
|
||||
const privateKey = constructKey(
|
||||
"private",
|
||||
extractable,
|
||||
usageIntersection(usages, ["sign"]),
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
|
||||
return { publicKey, privateKey };
|
||||
}
|
||||
case "HMAC": {
|
||||
// 1.
|
||||
if (
|
||||
|
@ -1967,6 +2112,439 @@
|
|||
}
|
||||
}
|
||||
|
||||
function importKeyEd25519(
|
||||
format,
|
||||
keyData,
|
||||
extractable,
|
||||
keyUsages,
|
||||
) {
|
||||
switch (format) {
|
||||
case "raw": {
|
||||
// 1.
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) => !ArrayPrototypeIncludes(["verify"], u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, keyData);
|
||||
|
||||
// 2-3.
|
||||
const algorithm = {
|
||||
name: "Ed25519",
|
||||
};
|
||||
|
||||
// 4-6.
|
||||
return constructKey(
|
||||
"public",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
case "spki": {
|
||||
// 1.
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) => !ArrayPrototypeIncludes(["verify"], u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const publicKeyData = new Uint8Array(32);
|
||||
if (!ops.op_import_spki_ed25519(keyData, publicKeyData)) {
|
||||
throw new DOMException("Invalid key data", "DataError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "Ed25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"public",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
case "pkcs8": {
|
||||
// 1.
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) => !ArrayPrototypeIncludes(["sign"], u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const privateKeyData = new Uint8Array(32);
|
||||
if (!ops.op_import_pkcs8_ed25519(keyData, privateKeyData)) {
|
||||
throw new DOMException("Invalid key data", "DataError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "Ed25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"private",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
case "jwk": {
|
||||
// 1.
|
||||
const jwk = keyData;
|
||||
|
||||
// 2.
|
||||
if (jwk.d !== undefined) {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) =>
|
||||
!ArrayPrototypeIncludes(
|
||||
["sign"],
|
||||
u,
|
||||
),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) =>
|
||||
!ArrayPrototypeIncludes(
|
||||
["verify"],
|
||||
u,
|
||||
),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
}
|
||||
|
||||
// 3.
|
||||
if (jwk.kty !== "OKP") {
|
||||
throw new DOMException("Invalid key type", "DataError");
|
||||
}
|
||||
|
||||
// 4.
|
||||
if (jwk.crv !== "Ed25519") {
|
||||
throw new DOMException("Invalid curve", "DataError");
|
||||
}
|
||||
|
||||
// 5.
|
||||
if (jwk.alg !== undefined && jwk.alg !== "EdDSA") {
|
||||
throw new DOMException("Invalid algorithm", "DataError");
|
||||
}
|
||||
|
||||
// 6.
|
||||
if (
|
||||
keyUsages.length > 0 && jwk.use !== undefined && jwk.use !== "sig"
|
||||
) {
|
||||
throw new DOMException("Invalid key usage", "DataError");
|
||||
}
|
||||
|
||||
// 7.
|
||||
if (jwk.key_ops !== undefined) {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
jwk.key_ops,
|
||||
(u) => !ArrayPrototypeIncludes(recognisedUsages, u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException(
|
||||
"'key_ops' property of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!ArrayPrototypeEvery(
|
||||
jwk.key_ops,
|
||||
(u) => ArrayPrototypeIncludes(keyUsages, u),
|
||||
)
|
||||
) {
|
||||
throw new DOMException(
|
||||
"'key_ops' property of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 8.
|
||||
if (jwk.ext !== undefined && jwk.ext === false && extractable) {
|
||||
throw new DOMException("Invalid key extractability", "DataError");
|
||||
}
|
||||
|
||||
// 9.
|
||||
if (jwk.d !== undefined) {
|
||||
// https://www.rfc-editor.org/rfc/rfc8037#section-2
|
||||
const privateKeyData = ops.op_crypto_base64url(jwk.d);
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "Ed25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"private",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
} else {
|
||||
// https://www.rfc-editor.org/rfc/rfc8037#section-2
|
||||
const publicKeyData = ops.op_crypto_base64url(jwk.d);
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "Ed25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"public",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new DOMException("Not implemented", "NotSupportedError");
|
||||
}
|
||||
}
|
||||
|
||||
function importKeyX25519(
|
||||
format,
|
||||
keyData,
|
||||
extractable,
|
||||
keyUsages,
|
||||
) {
|
||||
switch (format) {
|
||||
case "raw": {
|
||||
// 1.
|
||||
if (keyUsages.length > 0) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, keyData);
|
||||
|
||||
// 2-3.
|
||||
const algorithm = {
|
||||
name: "X25519",
|
||||
};
|
||||
|
||||
// 4-6.
|
||||
return constructKey(
|
||||
"public",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
case "spki": {
|
||||
// 1.
|
||||
if (keyUsages.length > 0) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const publicKeyData = new Uint8Array(32);
|
||||
if (!ops.op_import_spki_x25519(keyData, publicKeyData)) {
|
||||
throw new DOMException("Invalid key data", "DataError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "X25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"public",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
case "pkcs8": {
|
||||
// 1.
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
const privateKeyData = new Uint8Array(32);
|
||||
if (!ops.op_import_pkcs8_x25519(keyData, privateKeyData)) {
|
||||
throw new DOMException("Invalid key data", "DataError");
|
||||
}
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "X25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"private",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
case "jwk": {
|
||||
// 1.
|
||||
const jwk = keyData;
|
||||
|
||||
// 2.
|
||||
if (jwk.d !== undefined) {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
keyUsages,
|
||||
(u) =>
|
||||
!ArrayPrototypeIncludes(
|
||||
SUPPORTED_KEY_USAGES["X25519"].private,
|
||||
u,
|
||||
),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
}
|
||||
|
||||
// 3.
|
||||
if (jwk.d === undefined && keyUsages.length > 0) {
|
||||
throw new DOMException("Invalid key usages", "SyntaxError");
|
||||
}
|
||||
|
||||
// 4.
|
||||
if (jwk.kty !== "OKP") {
|
||||
throw new DOMException("Invalid key type", "DataError");
|
||||
}
|
||||
|
||||
// 5.
|
||||
if (jwk.crv !== "X25519") {
|
||||
throw new DOMException("Invalid curve", "DataError");
|
||||
}
|
||||
|
||||
// 6.
|
||||
if (keyUsages.length > 0 && jwk.use !== undefined) {
|
||||
if (jwk.use !== "enc") {
|
||||
throw new DOMException("Invalid key use", "DataError");
|
||||
}
|
||||
}
|
||||
|
||||
// 7.
|
||||
if (jwk.key_ops !== undefined) {
|
||||
if (
|
||||
ArrayPrototypeFind(
|
||||
jwk.key_ops,
|
||||
(u) => !ArrayPrototypeIncludes(recognisedUsages, u),
|
||||
) !== undefined
|
||||
) {
|
||||
throw new DOMException(
|
||||
"'key_ops' property of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!ArrayPrototypeEvery(
|
||||
jwk.key_ops,
|
||||
(u) => ArrayPrototypeIncludes(keyUsages, u),
|
||||
)
|
||||
) {
|
||||
throw new DOMException(
|
||||
"'key_ops' property of JsonWebKey is invalid",
|
||||
"DataError",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 8.
|
||||
if (jwk.ext !== undefined && jwk.ext === false && extractable) {
|
||||
throw new DOMException("Invalid key extractability", "DataError");
|
||||
}
|
||||
|
||||
// 9.
|
||||
if (jwk.d !== undefined) {
|
||||
// https://www.rfc-editor.org/rfc/rfc8037#section-2
|
||||
const privateKeyData = ops.op_crypto_base64url(jwk.d);
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "X25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"private",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
} else {
|
||||
// https://www.rfc-editor.org/rfc/rfc8037#section-2
|
||||
const publicKeyData = ops.op_crypto_base64url(jwk.d);
|
||||
|
||||
const handle = {};
|
||||
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
|
||||
|
||||
const algorithm = {
|
||||
name: "X25519",
|
||||
};
|
||||
|
||||
return constructKey(
|
||||
"public",
|
||||
extractable,
|
||||
[],
|
||||
algorithm,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new DOMException("Not implemented", "NotSupportedError");
|
||||
}
|
||||
}
|
||||
|
||||
function exportKeyAES(
|
||||
format,
|
||||
key,
|
||||
|
@ -2732,6 +3310,9 @@
|
|||
private: ["deriveKey", "deriveBits"],
|
||||
jwkUse: "enc",
|
||||
},
|
||||
"X25519": {
|
||||
private: ["deriveKey", "deriveBits"],
|
||||
},
|
||||
};
|
||||
|
||||
function importKeyRSA(
|
||||
|
@ -3430,6 +4011,66 @@
|
|||
}
|
||||
}
|
||||
|
||||
function exportKeyEd25519(format, key, innerKey) {
|
||||
switch (format) {
|
||||
case "raw": {
|
||||
// 1.
|
||||
if (key[_type] !== "public") {
|
||||
throw new DOMException(
|
||||
"Key is not a public key",
|
||||
"InvalidAccessError",
|
||||
);
|
||||
}
|
||||
|
||||
// 2-3.
|
||||
return innerKey.buffer;
|
||||
}
|
||||
case "spki": {
|
||||
// 1.
|
||||
if (key[_type] !== "public") {
|
||||
throw new DOMException(
|
||||
"Key is not a public key",
|
||||
"InvalidAccessError",
|
||||
);
|
||||
}
|
||||
|
||||
const spkiDer = ops.op_export_spki_ed25519(innerKey);
|
||||
return spkiDer.buffer;
|
||||
}
|
||||
case "pkcs8": {
|
||||
// 1.
|
||||
if (key[_type] !== "private") {
|
||||
throw new DOMException(
|
||||
"Key is not a public key",
|
||||
"InvalidAccessError",
|
||||
);
|
||||
}
|
||||
|
||||
const pkcs8Der = ops.op_export_pkcs8_ed25519(innerKey);
|
||||
return pkcs8Der.buffer;
|
||||
}
|
||||
case "jwk": {
|
||||
const x = key[_type] === "private"
|
||||
? ops.op_jwk_x_ed25519(innerKey)
|
||||
: ops.op_crypto_base64url(innerKey);
|
||||
const jwk = {
|
||||
kty: "OKP",
|
||||
alg: "EdDSA",
|
||||
crv: "Ed25519",
|
||||
x,
|
||||
"key_ops": key.usages,
|
||||
ext: key[_extractable],
|
||||
};
|
||||
if (key[_type] === "private") {
|
||||
jwk.d = ops.op_crypto_base64url(innerKey);
|
||||
}
|
||||
return jwk;
|
||||
}
|
||||
default:
|
||||
throw new DOMException("Not implemented", "NotSupportedError");
|
||||
}
|
||||
}
|
||||
|
||||
function exportKeyEC(format, key, innerKey) {
|
||||
switch (format) {
|
||||
case "raw": {
|
||||
|
@ -3713,6 +4354,49 @@
|
|||
|
||||
return buf.buffer;
|
||||
}
|
||||
case "X25519": {
|
||||
// 1.
|
||||
if (baseKey[_type] !== "private") {
|
||||
throw new DOMException("Invalid key type", "InvalidAccessError");
|
||||
}
|
||||
// 2.
|
||||
const publicKey = normalizedAlgorithm.public;
|
||||
// 3.
|
||||
if (publicKey[_type] !== "public") {
|
||||
throw new DOMException("Invalid key type", "InvalidAccessError");
|
||||
}
|
||||
// 4.
|
||||
if (publicKey[_algorithm].name !== baseKey[_algorithm].name) {
|
||||
throw new DOMException(
|
||||
"Algorithm mismatch",
|
||||
"InvalidAccessError",
|
||||
);
|
||||
}
|
||||
|
||||
// 5.
|
||||
const kHandle = baseKey[_handle];
|
||||
const k = WeakMapPrototypeGet(KEY_STORE, kHandle);
|
||||
|
||||
const uHandle = publicKey[_handle];
|
||||
const u = WeakMapPrototypeGet(KEY_STORE, uHandle);
|
||||
|
||||
const secret = new Uint8Array(32);
|
||||
const isIdentity = ops.op_derive_bits_x25519(k, u, secret);
|
||||
|
||||
// 6.
|
||||
if (isIdentity) {
|
||||
throw new DOMException("Invalid key", "OperationError");
|
||||
}
|
||||
|
||||
// 7.
|
||||
if (length === null) {
|
||||
return secret.buffer;
|
||||
} else if (secret.length * 8 < length) {
|
||||
throw new DOMException("Invalid length", "OperationError");
|
||||
} else {
|
||||
return secret.subarray(0, length / 8).buffer;
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new DOMException("Not implemented", "NotSupportedError");
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ block-modes = "0.9.1"
|
|||
cbc = { version = "0.1.2", features = ["alloc"] }
|
||||
const-oid = "0.9.0"
|
||||
ctr = "0.9.1"
|
||||
# https://github.com/dalek-cryptography/curve25519-dalek/pull/397
|
||||
curve25519-dalek = "2.1.3"
|
||||
deno_core = { version = "0.152.0", path = "../../core" }
|
||||
deno_web = { version = "0.101.0", path = "../web" }
|
||||
elliptic-curve = { version = "0.12.1", features = ["std", "pem"] }
|
||||
|
@ -40,3 +42,5 @@ sha2 = "0.10.2"
|
|||
spki = "0.6.0"
|
||||
tokio = { version = "1.21", features = ["full"] }
|
||||
uuid = { version = "1.0.0", features = ["v4"] }
|
||||
# https://github.com/dalek-cryptography/x25519-dalek/pull/89
|
||||
x25519-dalek = "2.0.0-pre.1"
|
||||
|
|
128
ext/crypto/ed25519.rs
Normal file
128
ext/crypto/ed25519.rs
Normal file
|
@ -0,0 +1,128 @@
|
|||
use deno_core::error::AnyError;
|
||||
use deno_core::op;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
use elliptic_curve::pkcs8::PrivateKeyInfo;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use ring::signature::Ed25519KeyPair;
|
||||
use ring::signature::KeyPair;
|
||||
use spki::der::Decode;
|
||||
use spki::der::Encode;
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_generate_ed25519_keypair(pkey: &mut [u8], pubkey: &mut [u8]) -> bool {
|
||||
let mut rng = OsRng;
|
||||
rng.fill_bytes(pkey);
|
||||
|
||||
let pair = match Ed25519KeyPair::from_seed_unchecked(pkey) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
};
|
||||
pubkey.copy_from_slice(pair.public_key().as_ref());
|
||||
true
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_sign_ed25519(key: &[u8], data: &[u8], signature: &mut [u8]) -> bool {
|
||||
let pair = match Ed25519KeyPair::from_seed_unchecked(key) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
};
|
||||
signature.copy_from_slice(pair.sign(data).as_ref());
|
||||
true
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_verify_ed25519(pubkey: &[u8], data: &[u8], signature: &[u8]) -> bool {
|
||||
ring::signature::UnparsedPublicKey::new(&ring::signature::ED25519, pubkey)
|
||||
.verify(data, signature)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
// id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
|
||||
pub const ED25519_OID: const_oid::ObjectIdentifier =
|
||||
const_oid::ObjectIdentifier::new_unwrap("1.3.101.112");
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_import_spki_ed25519(key_data: &[u8], out: &mut [u8]) -> bool {
|
||||
// 2-3.
|
||||
let pk_info = match spki::SubjectPublicKeyInfo::from_der(key_data) {
|
||||
Ok(pk_info) => pk_info,
|
||||
Err(_) => return false,
|
||||
};
|
||||
// 4.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
if alg != ED25519_OID {
|
||||
return false;
|
||||
}
|
||||
// 5.
|
||||
if pk_info.algorithm.parameters.is_some() {
|
||||
return false;
|
||||
}
|
||||
out.copy_from_slice(pk_info.subject_public_key);
|
||||
true
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_import_pkcs8_ed25519(key_data: &[u8], out: &mut [u8]) -> bool {
|
||||
// 2-3.
|
||||
let pk_info = match PrivateKeyInfo::from_der(key_data) {
|
||||
Ok(pk_info) => pk_info,
|
||||
Err(_) => return false,
|
||||
};
|
||||
// 4.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
if alg != ED25519_OID {
|
||||
return false;
|
||||
}
|
||||
// 5.
|
||||
if pk_info.algorithm.parameters.is_some() {
|
||||
return false;
|
||||
}
|
||||
// 6.
|
||||
// CurvePrivateKey ::= OCTET STRING
|
||||
if pk_info.private_key.len() != 32 {
|
||||
return false;
|
||||
}
|
||||
out.copy_from_slice(pk_info.private_key);
|
||||
true
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_export_spki_ed25519(pubkey: &[u8]) -> Result<ZeroCopyBuf, AnyError> {
|
||||
let key_info = spki::SubjectPublicKeyInfo {
|
||||
algorithm: spki::AlgorithmIdentifier {
|
||||
// id-Ed25519
|
||||
oid: ED25519_OID,
|
||||
parameters: None,
|
||||
},
|
||||
subject_public_key: pubkey,
|
||||
};
|
||||
Ok(key_info.to_vec()?.into())
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_export_pkcs8_ed25519(pkey: &[u8]) -> Result<ZeroCopyBuf, AnyError> {
|
||||
let pk_info = rsa::pkcs8::PrivateKeyInfo {
|
||||
public_key: None,
|
||||
algorithm: rsa::pkcs8::AlgorithmIdentifier {
|
||||
// id-Ed25519
|
||||
oid: ED25519_OID,
|
||||
parameters: None,
|
||||
},
|
||||
private_key: pkey, // OCTET STRING
|
||||
};
|
||||
|
||||
Ok(pk_info.to_vec()?.into())
|
||||
}
|
||||
|
||||
// 'x' from Section 2 of RFC 8037
|
||||
// https://www.rfc-editor.org/rfc/rfc8037#section-2
|
||||
#[op]
|
||||
pub fn op_jwk_x_ed25519(pkey: &[u8]) -> Result<String, AnyError> {
|
||||
let pair = Ed25519KeyPair::from_seed_unchecked(pkey)?;
|
||||
Ok(base64::encode_config(
|
||||
pair.public_key().as_ref(),
|
||||
base64::URL_SAFE_NO_PAD,
|
||||
))
|
||||
}
|
|
@ -55,12 +55,14 @@ use std::path::PathBuf;
|
|||
pub use rand; // Re-export rand
|
||||
|
||||
mod decrypt;
|
||||
mod ed25519;
|
||||
mod encrypt;
|
||||
mod export_key;
|
||||
mod generate_key;
|
||||
mod import_key;
|
||||
mod key;
|
||||
mod shared;
|
||||
mod x25519;
|
||||
|
||||
pub use crate::decrypt::op_crypto_decrypt;
|
||||
pub use crate::encrypt::op_crypto_encrypt;
|
||||
|
@ -98,6 +100,19 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
|
|||
op_crypto_random_uuid::decl(),
|
||||
op_crypto_wrap_key::decl(),
|
||||
op_crypto_unwrap_key::decl(),
|
||||
op_crypto_base64url::decl(),
|
||||
x25519::op_generate_x25519_keypair::decl(),
|
||||
x25519::op_derive_bits_x25519::decl(),
|
||||
x25519::op_import_spki_x25519::decl(),
|
||||
x25519::op_import_pkcs8_x25519::decl(),
|
||||
ed25519::op_generate_ed25519_keypair::decl(),
|
||||
ed25519::op_import_spki_ed25519::decl(),
|
||||
ed25519::op_import_pkcs8_ed25519::decl(),
|
||||
ed25519::op_sign_ed25519::decl(),
|
||||
ed25519::op_verify_ed25519::decl(),
|
||||
ed25519::op_export_spki_ed25519::decl(),
|
||||
ed25519::op_export_pkcs8_ed25519::decl(),
|
||||
ed25519::op_jwk_x_ed25519::decl(),
|
||||
])
|
||||
.state(move |state| {
|
||||
if let Some(seed) = maybe_seed {
|
||||
|
@ -108,6 +123,13 @@ pub fn init(maybe_seed: Option<u64>) -> Extension {
|
|||
.build()
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_crypto_base64url(data: String) -> ZeroCopyBuf {
|
||||
let data: Vec<u8> =
|
||||
base64::encode_config(data, base64::URL_SAFE_NO_PAD).into();
|
||||
data.into()
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_crypto_get_random_values(
|
||||
state: &mut OpState,
|
||||
|
|
89
ext/crypto/x25519.rs
Normal file
89
ext/crypto/x25519.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use deno_core::op;
|
||||
use elliptic_curve::pkcs8::PrivateKeyInfo;
|
||||
use elliptic_curve::subtle::ConstantTimeEq;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use spki::der::Decode;
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_generate_x25519_keypair(pkey: &mut [u8], 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
|
||||
// pubkey = x25519(a, 9) which is constant-time Montgomery ladder.
|
||||
// https://eprint.iacr.org/2014/140.pdf page 4
|
||||
// https://eprint.iacr.org/2017/212.pdf algorithm 8
|
||||
// pubkey is in LE order.
|
||||
let pkey: [u8; 32] = pkey.try_into().expect("Expected byteLength 32");
|
||||
pubkey.copy_from_slice(&x25519_dalek::x25519(pkey, X25519_BASEPOINT_BYTES));
|
||||
}
|
||||
|
||||
const MONTGOMERY_IDENTITY: MontgomeryPoint = MontgomeryPoint([0; 32]);
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_derive_bits_x25519(k: &[u8], u: &[u8], secret: &mut [u8]) -> bool {
|
||||
let k: [u8; 32] = k.try_into().expect("Expected byteLength 32");
|
||||
let u: [u8; 32] = u.try_into().expect("Expected byteLength 32");
|
||||
let sh_sec = x25519_dalek::x25519(k, u);
|
||||
let point = MontgomeryPoint(sh_sec);
|
||||
if point.ct_eq(&MONTGOMERY_IDENTITY).unwrap_u8() == 1 {
|
||||
return false;
|
||||
}
|
||||
secret.copy_from_slice(&sh_sec);
|
||||
true
|
||||
}
|
||||
|
||||
// id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 }
|
||||
pub const X25519_OID: const_oid::ObjectIdentifier =
|
||||
const_oid::ObjectIdentifier::new_unwrap("1.3.101.110");
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_import_spki_x25519(key_data: &[u8], out: &mut [u8]) -> bool {
|
||||
// 2-3.
|
||||
let pk_info = match spki::SubjectPublicKeyInfo::from_der(key_data) {
|
||||
Ok(pk_info) => pk_info,
|
||||
Err(_) => return false,
|
||||
};
|
||||
// 4.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
if alg != X25519_OID {
|
||||
return false;
|
||||
}
|
||||
// 5.
|
||||
if pk_info.algorithm.parameters.is_some() {
|
||||
return false;
|
||||
}
|
||||
out.copy_from_slice(pk_info.subject_public_key);
|
||||
true
|
||||
}
|
||||
|
||||
#[op(fast)]
|
||||
pub fn op_import_pkcs8_x25519(key_data: &[u8], out: &mut [u8]) -> bool {
|
||||
// 2-3.
|
||||
let pk_info = match PrivateKeyInfo::from_der(key_data) {
|
||||
Ok(pk_info) => pk_info,
|
||||
Err(_) => return false,
|
||||
};
|
||||
// 4.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
if alg != X25519_OID {
|
||||
return false;
|
||||
}
|
||||
// 5.
|
||||
if pk_info.algorithm.parameters.is_some() {
|
||||
return false;
|
||||
}
|
||||
// 6.
|
||||
// CurvePrivateKey ::= OCTET STRING
|
||||
if pk_info.private_key.len() != 32 {
|
||||
return false;
|
||||
}
|
||||
out.copy_from_slice(pk_info.private_key);
|
||||
true
|
||||
}
|
|
@ -573,62 +573,8 @@
|
|||
"successes_RSASSA-PKCS1-v1_5.https.any.worker.html?11-20": true,
|
||||
"successes_RSASSA-PKCS1-v1_5.https.any.worker.html?21-30": true,
|
||||
"successes_RSASSA-PKCS1-v1_5.https.any.worker.html?31-last": true,
|
||||
"failures_Ed25519.https.any.html": [
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [deriveBits])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, deriveBits])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, deriveBits])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, deriveBits])",
|
||||
"Empty usages: generateKey({name: Ed25519}, false, [])",
|
||||
"Empty usages: generateKey({name: Ed25519}, true, [])"
|
||||
],
|
||||
"failures_Ed25519.https.any.worker.html": [
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, encrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, decrypt])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, wrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, unwrapKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, deriveKey])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [deriveBits])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, deriveBits])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [verify, sign, deriveBits])",
|
||||
"Bad usages: generateKey({name: Ed25519}, true, [sign, verify, sign, sign, verify, deriveBits])",
|
||||
"Empty usages: generateKey({name: Ed25519}, false, [])",
|
||||
"Empty usages: generateKey({name: Ed25519}, true, [])"
|
||||
],
|
||||
"failures_Ed25519.https.any.html": true,
|
||||
"failures_Ed25519.https.any.worker.html": true,
|
||||
"failures_Ed448.https.any.html": [
|
||||
"Bad usages: generateKey({name: Ed448}, true, [encrypt])",
|
||||
"Bad usages: generateKey({name: Ed448}, true, [sign, encrypt])",
|
||||
|
@ -685,74 +631,8 @@
|
|||
"Empty usages: generateKey({name: Ed448}, false, [])",
|
||||
"Empty usages: generateKey({name: Ed448}, true, [])"
|
||||
],
|
||||
"failures_X25519.https.any.html": [
|
||||
"Bad usages: generateKey({name: X25519}, true, [encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey])",
|
||||
"Empty usages: generateKey({name: X25519}, false, [])",
|
||||
"Empty usages: generateKey({name: X25519}, true, [])"
|
||||
],
|
||||
"failures_X25519.https.any.worker.html": [
|
||||
"Bad usages: generateKey({name: X25519}, true, [encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, deriveKey, unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveBits, unwrapKey])",
|
||||
"Bad usages: generateKey({name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey])",
|
||||
"Empty usages: generateKey({name: X25519}, false, [])",
|
||||
"Empty usages: generateKey({name: X25519}, true, [])"
|
||||
],
|
||||
"failures_X25519.https.any.html": true,
|
||||
"failures_X25519.https.any.worker.html": true,
|
||||
"failures_X448.https.any.html": [
|
||||
"Bad usages: generateKey({name: X448}, true, [encrypt])",
|
||||
"Bad usages: generateKey({name: X448}, true, [deriveKey, encrypt])",
|
||||
|
@ -821,12 +701,12 @@
|
|||
"Empty usages: generateKey({name: X448}, false, [])",
|
||||
"Empty usages: generateKey({name: X448}, true, [])"
|
||||
],
|
||||
"successes_Ed25519.https.any.html": false,
|
||||
"successes_Ed25519.https.any.worker.html": false,
|
||||
"successes_Ed25519.https.any.html": true,
|
||||
"successes_Ed25519.https.any.worker.html": true,
|
||||
"successes_Ed448.https.any.html": false,
|
||||
"successes_Ed448.https.any.worker.html": false,
|
||||
"successes_X25519.https.any.html": false,
|
||||
"successes_X25519.https.any.worker.html": false,
|
||||
"successes_X25519.https.any.html": true,
|
||||
"successes_X25519.https.any.worker.html": true,
|
||||
"successes_X448.https.any.html": false,
|
||||
"successes_X448.https.any.worker.html": false
|
||||
},
|
||||
|
@ -899,8 +779,98 @@
|
|||
"rsa_importKey.https.any.worker.html": true,
|
||||
"symmetric_importKey.https.any.html": true,
|
||||
"symmetric_importKey.https.any.worker.html": true,
|
||||
"okp_importKey.https.any.html": false,
|
||||
"okp_importKey.https.any.worker.html": false
|
||||
"okp_importKey.https.any.html": [
|
||||
"Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, true, [])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, true, [])",
|
||||
"Good parameters: Ed25519 bits (pkcs8, buffer(48), {name: Ed25519}, true, [sign])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])",
|
||||
"Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, false, [])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, false, [])",
|
||||
"Good parameters: Ed25519 bits (pkcs8, buffer(48), {name: Ed25519}, false, [sign])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), {name: Ed25519}, false, [sign])",
|
||||
"Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, true, [])",
|
||||
"Good parameters: Ed448 bits (jwk, object(kty, crv, x), {name: Ed448}, true, [])",
|
||||
"Good parameters: Ed448 bits (pkcs8, buffer(73), {name: Ed448}, true, [sign])",
|
||||
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, true, [sign])",
|
||||
"Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, false, [])",
|
||||
"Good parameters: Ed448 bits (jwk, object(kty, crv, x), {name: Ed448}, false, [])",
|
||||
"Good parameters: Ed448 bits (pkcs8, buffer(73), {name: Ed448}, false, [sign])",
|
||||
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, false, [sign])",
|
||||
"Good parameters: X25519 bits (spki, buffer(44), {name: X25519}, true, [])",
|
||||
"Good parameters: X25519 bits (jwk, object(kty, crv, x), {name: X25519}, true, [])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, true, [deriveKey])",
|
||||
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, true, [deriveBits])",
|
||||
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
|
||||
"Good parameters: X25519 bits (jwk, object(kty, crv, x), {name: X25519}, false, [])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, false, [deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, false, [deriveBits, deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, false, [deriveBits])",
|
||||
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, true, [])",
|
||||
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, true, [])",
|
||||
"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: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveBits])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveBits])",
|
||||
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, false, [])",
|
||||
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, false, [])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])"
|
||||
],
|
||||
"okp_importKey.https.any.worker.html": [
|
||||
"Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, true, [])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, true, [])",
|
||||
"Good parameters: Ed25519 bits (pkcs8, buffer(48), {name: Ed25519}, true, [sign])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])",
|
||||
"Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, false, [])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, false, [])",
|
||||
"Good parameters: Ed25519 bits (pkcs8, buffer(48), {name: Ed25519}, false, [sign])",
|
||||
"Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), {name: Ed25519}, false, [sign])",
|
||||
"Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, true, [])",
|
||||
"Good parameters: Ed448 bits (jwk, object(kty, crv, x), {name: Ed448}, true, [])",
|
||||
"Good parameters: Ed448 bits (pkcs8, buffer(73), {name: Ed448}, true, [sign])",
|
||||
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, true, [sign])",
|
||||
"Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, false, [])",
|
||||
"Good parameters: Ed448 bits (jwk, object(kty, crv, x), {name: Ed448}, false, [])",
|
||||
"Good parameters: Ed448 bits (pkcs8, buffer(73), {name: Ed448}, false, [sign])",
|
||||
"Good parameters: Ed448 bits (jwk, object(crv, d, x, kty), {name: Ed448}, false, [sign])",
|
||||
"Good parameters: X25519 bits (spki, buffer(44), {name: X25519}, true, [])",
|
||||
"Good parameters: X25519 bits (jwk, object(kty, crv, x), {name: X25519}, true, [])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, true, [deriveKey])",
|
||||
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, true, [deriveBits])",
|
||||
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
|
||||
"Good parameters: X25519 bits (jwk, object(kty, crv, x), {name: X25519}, false, [])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, false, [deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, false, [deriveBits, deriveKey])",
|
||||
"Good parameters: X25519 bits (pkcs8, buffer(48), {name: X25519}, false, [deriveBits])",
|
||||
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, true, [])",
|
||||
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, true, [])",
|
||||
"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: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveBits])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveBits])",
|
||||
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, false, [])",
|
||||
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, false, [])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits, deriveKey])",
|
||||
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])",
|
||||
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])"
|
||||
]
|
||||
},
|
||||
"randomUUID.https.any.html": true,
|
||||
"randomUUID.https.any.worker.html": true,
|
||||
|
|
Loading…
Add table
Reference in a new issue