Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions ext/crypto/export_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand All @@ -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()
}
};

Expand All @@ -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 {
Expand Down Expand Up @@ -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()?;
Expand Down Expand Up @@ -402,7 +424,29 @@ fn export_key_ec(
Err(data_error("expected valid public EC key"))
}
}
_ => Err(not_supported_error("Unsupported namedCurve")),

EcNamedCurve::P521 => {
let ec_key =
p521::SecretKey::from_pkcs8_der(private_key).map_err(|_| {
custom_error(
"DOMExceptionOperationError",
"failed to decode private key",
)
})?;

let point = ec_key.public_key().to_encoded_point(false);
if let elliptic_curve::sec1::Coordinates::Uncompressed { x, y } =
point.coordinates()
{
Ok(ExportKeyResult::JwkPrivateEc {
x: bytes_to_b64(x),
y: bytes_to_b64(y),
d: bytes_to_b64(&ec_key.to_bytes()),
})
} else {
Err(data_error("expected valid public EC key"))
}
}
}
}
ExportKeyFormat::JwkSecret => Err(unsupported_format()),
Expand Down
11 changes: 6 additions & 5 deletions ext/crypto/import_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,11 @@ 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)?;

pk.to_pkcs8_der()
.map_err(|_| data_error("invalid JWK private key"))?
}
};

Expand Down Expand Up @@ -652,7 +656,7 @@ fn import_key_ec(
// 2-7
// Deserialize PKCS8 - validate structure, extracts named_curve
let named_curve_alg = match named_curve {
EcNamedCurve::P256 | EcNamedCurve::P384 => {
EcNamedCurve::P256 | EcNamedCurve::P384 | EcNamedCurve::P521 => {
let pk = PrivateKeyInfo::from_der(data.as_ref())
.map_err(|_| data_error("expected valid PKCS#8 data"))?;
pk.algorithm
Expand All @@ -661,9 +665,6 @@ fn import_key_ec(
.try_into()
.unwrap()
}
EcNamedCurve::P521 => {
return Err(data_error("Unsupported named curve"))
}
};

// 8-9.
Expand Down
17 changes: 17 additions & 0 deletions ext/crypto/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,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),
Expand Down