diff options
-rw-r--r-- | cli/tests/unit/webcrypto_test.ts | 48 | ||||
-rw-r--r-- | ext/crypto/lib.rs | 42 |
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 => { |