summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiachedelic <diachedelic@gmail.com>2022-07-24 03:04:37 +1000
committerGitHub <noreply@github.com>2022-07-23 22:34:37 +0530
commit2843160fc79a9651e9b2c2ddc4f834c15e138db6 (patch)
tree28e4308120979e954df6254d6d0394d908a75d81
parent504d2936ecf1a5520ca20f83792a94b219e84f53 (diff)
feat(ext/crypto): deriveBits P-384 (#15138)
This commit adds P-384 curve support for crypto.subtle.deriveBits. Co-authored-by: James Diacono <james@diacono.com.au>
-rw-r--r--cli/tests/unit/webcrypto_test.ts48
-rw-r--r--ext/crypto/lib.rs42
2 files changed, 61 insertions, 29 deletions
diff --git a/cli/tests/unit/webcrypto_test.ts b/cli/tests/unit/webcrypto_test.ts
index ea2c05781..a6cab93dd 100644
--- a/cli/tests/unit/webcrypto_test.ts
+++ b/cli/tests/unit/webcrypto_test.ts
@@ -716,27 +716,28 @@ Deno.test(async function testAesCtrEncryptDecrypt() {
});
Deno.test(async function testECDH() {
- const namedCurve = "P-256";
- const keyPair = await crypto.subtle.generateKey(
- {
- name: "ECDH",
- namedCurve,
- },
- true,
- ["deriveBits"],
- );
+ for (const keySize of [256, 384]) {
+ const keyPair = await crypto.subtle.generateKey(
+ {
+ name: "ECDH",
+ namedCurve: "P-" + keySize,
+ },
+ true,
+ ["deriveBits"],
+ );
- const derivedKey = await crypto.subtle.deriveBits(
- {
- name: "ECDH",
- public: keyPair.publicKey,
- },
- keyPair.privateKey,
- 256,
- );
+ const derivedKey = await crypto.subtle.deriveBits(
+ {
+ name: "ECDH",
+ public: keyPair.publicKey,
+ },
+ keyPair.privateKey,
+ keySize,
+ );
- assert(derivedKey instanceof ArrayBuffer);
- assertEquals(derivedKey.byteLength, 256 / 8);
+ assert(derivedKey instanceof ArrayBuffer);
+ assertEquals(derivedKey.byteLength, keySize / 8);
+ }
});
Deno.test(async function testWrapKey() {
@@ -1299,22 +1300,17 @@ Deno.test(async function testImportEcDhJwk() {
);
assert(equalJwk(publicJWK, expPublicKeyJWK as JWK));
- // deriveBits still not implemented for P384
- if (size != 256) {
- continue;
- }
-
const derivedKey = await subtle.deriveBits(
{
name: "ECDH",
public: publicKeyECDH,
},
privateKeyECDH,
- 256,
+ size,
);
assert(derivedKey instanceof ArrayBuffer);
- assertEquals(derivedKey.byteLength, 256 / 8);
+ assertEquals(derivedKey.byteLength, size / 8);
}
});
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index a5c0d90e9..f4e118626 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -556,9 +556,45 @@ pub async fn op_crypto_derive_bits(
// raw serialized x-coordinate of the computed point
Ok(shared_secret.raw_secret_bytes().to_vec().into())
}
- // TODO(@littledivy): support for P384
- // https://github.com/RustCrypto/elliptic-curves/issues/240
- _ => Err(type_error("Unsupported namedCurve".to_string())),
+ CryptoNamedCurve::P384 => {
+ let secret_key = p384::SecretKey::from_pkcs8_der(&args.key.data)
+ .map_err(|_| type_error("Unexpected error decoding private key"))?;
+
+ let public_key = match public_key.r#type {
+ KeyType::Private => {
+ p384::SecretKey::from_pkcs8_der(&public_key.data)
+ .map_err(|_| {
+ type_error("Unexpected error decoding private key")
+ })?
+ .public_key()
+ }
+ KeyType::Public => {
+ let point = p384::EncodedPoint::from_bytes(public_key.data)
+ .map_err(|_| {
+ type_error("Unexpected error decoding private key")
+ })?;
+
+ let pk = p384::PublicKey::from_encoded_point(&point);
+ // pk is a constant time Option.
+ if pk.is_some().into() {
+ pk.unwrap()
+ } else {
+ return Err(type_error(
+ "Unexpected error decoding private key",
+ ));
+ }
+ }
+ _ => unreachable!(),
+ };
+
+ let shared_secret = p384::elliptic_curve::ecdh::diffie_hellman(
+ secret_key.to_nonzero_scalar(),
+ public_key.as_affine(),
+ );
+
+ // raw serialized x-coordinate of the computed point
+ Ok(shared_secret.raw_secret_bytes().to_vec().into())
+ }
}
}
Algorithm::Hkdf => {