diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/crypto/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/crypto/export_key.rs | 34 | ||||
-rw-r--r-- | ext/crypto/import_key.rs | 77 | ||||
-rw-r--r-- | ext/crypto/shared.rs | 17 | ||||
-rw-r--r-- | ext/node/Cargo.toml | 2 |
5 files changed, 64 insertions, 67 deletions
diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml index beea81d1e..3f2a8d703 100644 --- a/ext/crypto/Cargo.toml +++ b/ext/crypto/Cargo.toml @@ -33,6 +33,7 @@ p521 = "0.13.3" rand.workspace = true ring = { workspace = true, features = ["std"] } rsa.workspace = true +sec1.workspace = true serde.workspace = true serde_bytes.workspace = true sha1.workspace = true diff --git a/ext/crypto/export_key.rs b/ext/crypto/export_key.rs index 588e9978b..00ce7e11c 100644 --- a/ext/crypto/export_key.rs +++ b/ext/crypto/export_key.rs @@ -254,7 +254,9 @@ fn export_key_ec( point.as_ref().to_vec() } EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) + let point = key_data.as_ec_public_key_p521()?; + + point.as_ref().to_vec() } }; Ok(ExportKeyResult::Raw(subject_public_key.into())) @@ -272,7 +274,9 @@ fn export_key_ec( point.as_ref().to_vec() } EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) + let point = key_data.as_ec_public_key_p521()?; + + point.as_ref().to_vec() } }; @@ -285,9 +289,10 @@ fn export_key_ec( oid: elliptic_curve::ALGORITHM_OID, parameters: Some((&p384::NistP384::OID).into()), }, - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } + EcNamedCurve::P521 => AlgorithmIdentifierOwned { + oid: elliptic_curve::ALGORITHM_OID, + parameters: Some((&p521::NistP521::OID).into()), + }, }; let alg_id = match algorithm { @@ -351,7 +356,24 @@ fn export_key_ec( )) } } - EcNamedCurve::P521 => Err(data_error("Unsupported named curve")), + EcNamedCurve::P521 => { + let point = key_data.as_ec_public_key_p521()?; + let coords = point.coordinates(); + + if let p521::elliptic_curve::sec1::Coordinates::Uncompressed { x, y } = + coords + { + Ok(ExportKeyResult::JwkPublicEc { + x: bytes_to_b64(x), + y: bytes_to_b64(y), + }) + } else { + Err(custom_error( + "DOMExceptionOperationError", + "failed to decode public key", + )) + } + } }, ExportKeyFormat::JwkPrivate => { let private_key = key_data.as_ec_private_key()?; diff --git a/ext/crypto/import_key.rs b/ext/crypto/import_key.rs index 88265a2cd..e30baea03 100644 --- a/ext/crypto/import_key.rs +++ b/ext/crypto/import_key.rs @@ -7,14 +7,12 @@ use deno_core::JsBuffer; use deno_core::ToJsBuffer; use elliptic_curve::pkcs8::PrivateKeyInfo; use p256::pkcs8::EncodePrivateKey; -use ring::signature::EcdsaKeyPair; use rsa::pkcs1::UintRef; use rsa::pkcs8::der::Encode; use serde::Deserialize; use serde::Serialize; use spki::der::Decode; -use crate::key::CryptoNamedCurve; use crate::shared::*; #[derive(Deserialize)] @@ -45,7 +43,9 @@ pub enum KeyData { y: String, }, JwkPrivateEc { + #[allow(dead_code)] x: String, + #[allow(dead_code)] y: String, d: String, }, @@ -543,9 +543,7 @@ fn import_key_ec_jwk( raw_data: RustRawKeyData::Public(point_bytes.into()), }) } - KeyData::JwkPrivateEc { d, x, y } => { - jwt_b64_int_or_err!(private_d, &d, "invalid JWK private key"); - let point_bytes = import_key_ec_jwk_to_point(x, y, named_curve)?; + KeyData::JwkPrivateEc { d, .. } => { let pkcs8_der = match named_curve { EcNamedCurve::P256 => { let d = decode_b64url_to_field_bytes::<p256::NistP256>(&d)?; @@ -562,27 +560,14 @@ fn import_key_ec_jwk( .map_err(|_| data_error("invalid JWK private key"))? } EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } - }; + let d = decode_b64url_to_field_bytes::<p521::NistP521>(&d)?; + let pk = p521::SecretKey::from_bytes(&d)?; - // Import using ring, to validate key - let key_alg = match named_curve { - EcNamedCurve::P256 => CryptoNamedCurve::P256.into(), - EcNamedCurve::P384 => CryptoNamedCurve::P256.into(), - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) + pk.to_pkcs8_der() + .map_err(|_| data_error("invalid JWK private key"))? } }; - let rng = ring::rand::SystemRandom::new(); - let _key_pair = EcdsaKeyPair::from_private_key_and_public_key( - key_alg, - private_d.as_bytes(), - point_bytes.as_ref(), - &rng, - ); - Ok(ImportKeyResult::Ec { raw_data: RustRawKeyData::Private(pkcs8_der.as_bytes().to_vec().into()), }) @@ -649,24 +634,15 @@ fn import_key_ec( }) } KeyData::Pkcs8(data) => { - // 2-7 - // Deserialize PKCS8 - validate structure, extracts named_curve - let named_curve_alg = match named_curve { - EcNamedCurve::P256 | EcNamedCurve::P384 => { - let pk = PrivateKeyInfo::from_der(data.as_ref()) - .map_err(|_| data_error("expected valid PKCS#8 data"))?; - pk.algorithm - .parameters - .ok_or_else(|| data_error("malformed parameters"))? - .try_into() - .unwrap() - } - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } - }; + let pk = PrivateKeyInfo::from_der(data.as_ref()) + .map_err(|_| data_error("expected valid PKCS#8 data"))?; + let named_curve_alg = pk + .algorithm + .parameters + .ok_or_else(|| data_error("malformed parameters"))? + .try_into() + .unwrap(); - // 8-9. let pk_named_curve = match named_curve_alg { // id-secp256r1 ID_SECP256R1_OID => Some(EcNamedCurve::P256), @@ -677,27 +653,8 @@ fn import_key_ec( _ => None, }; - // 10. - if let Some(pk_named_curve) = pk_named_curve { - let signing_alg = match pk_named_curve { - EcNamedCurve::P256 => CryptoNamedCurve::P256.into(), - EcNamedCurve::P384 => CryptoNamedCurve::P384.into(), - EcNamedCurve::P521 => { - return Err(data_error("Unsupported named curve")) - } - }; - - let rng = ring::rand::SystemRandom::new(); - // deserialize pkcs8 using ring crate, to VALIDATE public key - let _private_key = EcdsaKeyPair::from_pkcs8(signing_alg, &data, &rng) - .map_err(|_| data_error("invalid key"))?; - - // 11. - if named_curve != pk_named_curve { - return Err(data_error("curve mismatch")); - } - } else { - return Err(data_error("Unsupported named curve")); + if pk_named_curve != Some(named_curve) { + return Err(data_error("curve mismatch")); } Ok(ImportKeyResult::Ec { diff --git a/ext/crypto/shared.rs b/ext/crypto/shared.rs index d5b2d6593..d06a268cd 100644 --- a/ext/crypto/shared.rs +++ b/ext/crypto/shared.rs @@ -126,6 +126,23 @@ impl V8RawKeyData { } } + pub fn as_ec_public_key_p521(&self) -> Result<p521::EncodedPoint, AnyError> { + match self { + V8RawKeyData::Public(data) => { + // public_key is a serialized EncodedPoint + p521::EncodedPoint::from_bytes(data) + .map_err(|_| type_error("expected valid public EC key")) + } + V8RawKeyData::Private(data) => { + let signing_key = p521::SecretKey::from_pkcs8_der(data) + .map_err(|_| type_error("expected valid private EC key"))?; + Ok(signing_key.public_key().to_encoded_point(false)) + } + // Should never reach here. + V8RawKeyData::Secret(_) => unreachable!(), + } + } + pub fn as_ec_private_key(&self) -> Result<&[u8], AnyError> { match self { V8RawKeyData::Private(data) => Ok(data), diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml index 24e7ecf2e..1cd97e3e8 100644 --- a/ext/node/Cargo.toml +++ b/ext/node/Cargo.toml @@ -81,7 +81,7 @@ ring.workspace = true ripemd = { version = "0.1.3", features = ["oid"] } rsa.workspace = true scrypt = "0.11.0" -sec1 = "0.7" +sec1.workspace = true serde = "1.0.149" sha1.workspace = true sha2.workspace = true |