Skip to main content

polymorph_webcrypto_guest/
ecdsa.rs

1//! `ecdsa-verify` / `ecdsa-sign` key creation.
2
3use crate::{bindings, Error, SigningKey, SigningKeyOptions, UnwrapInput, VerifyingKey};
4
5pub use crate::bindings::ecdsa_verify::EcdsaVariant;
6
7/// Import a public key as an uncompressed SEC1 point.
8pub async fn import_verifying_key_raw(
9    variant: EcdsaVariant,
10    raw: impl Into<Vec<u8>>,
11) -> Result<VerifyingKey, Error> {
12    Ok(VerifyingKey::from_raw(
13        bindings::ecdsa_verify::import_verifying_key_raw(variant, raw.into()).await?,
14    ))
15}
16
17/// Import a public key as an X.509 SubjectPublicKeyInfo (DER). The curve
18/// must be named by OID and match the declared variant's, or the import
19/// fails [`Error::InvalidKey`]; whether a *compressed* point encoding is
20/// accepted is implementation-defined — do not rely on either behavior
21/// (see the WIT `import-verifying-key-spki` doc).
22pub async fn import_verifying_key_spki(
23    variant: EcdsaVariant,
24    spki: impl Into<Vec<u8>>,
25) -> Result<VerifyingKey, Error> {
26    Ok(VerifyingKey::from_raw(
27        bindings::ecdsa_verify::import_verifying_key_spki(variant, spki.into()).await?,
28    ))
29}
30
31/// Import a public key as an EC public JWK (`kty: "EC"`, with `crv`,
32/// `x`, and `y`; as JSON text). The JWK's `crv` must match the declared
33/// variant's curve, and an `alg` member, when present, must be the
34/// curve's JOSE signature alg (`"ES256"` for P-256, `"ES384"` for
35/// P-384). See the WIT `mac-key.export-key-jwk` doc for the package-wide
36/// JWK contract.
37pub async fn import_verifying_key_jwk(
38    variant: EcdsaVariant,
39    jwk: impl Into<String>,
40) -> Result<VerifyingKey, Error> {
41    Ok(VerifyingKey::from_raw(
42        bindings::ecdsa_verify::import_verifying_key_jwk(variant, jwk.into()).await?,
43    ))
44}
45
46/// Generate a fresh random signing key of the declared variant, returning
47/// both halves.
48pub async fn generate_key(
49    variant: EcdsaVariant,
50    options: SigningKeyOptions,
51) -> Result<(SigningKey, VerifyingKey), Error> {
52    let (signing, verifying) = bindings::ecdsa_sign::generate_key(variant, options.lower()).await?;
53    Ok((
54        SigningKey::from_raw(signing),
55        VerifyingKey::from_raw(verifying),
56    ))
57}
58
59/// Import a signing key as a PKCS#8 PrivateKeyInfo (DER, the SEC1
60/// private-key body). The encoded curve must match the declared
61/// variant's ([`Error::InvalidKey`]); an embedded public key, when
62/// present, is validated against the scalar and never trusted on its
63/// own. Returns only the signing key; the public half is imported
64/// separately (there is no derive from a private import — see the WIT
65/// `ecdsa-sign` interface doc).
66pub async fn import_signing_key_pkcs8(
67    variant: EcdsaVariant,
68    pkcs8: impl Into<Vec<u8>>,
69    options: SigningKeyOptions,
70) -> Result<SigningKey, Error> {
71    Ok(SigningKey::from_raw(
72        bindings::ecdsa_sign::import_signing_key_pkcs8(variant, pkcs8.into(), options.lower())
73            .await?,
74    ))
75}
76
77/// Import a signing key as an EC private JWK (`kty: "EC"`, with `crv`,
78/// `d`, and the mandatory public coordinates `x`/`y`; as JSON text).
79/// `crv` and `alg` are validated as in [`import_verifying_key_jwk`].
80///
81/// Security: implementations MAY validate `x`/`y` against `d`, and never
82/// trust them for any operation.
83pub async fn import_signing_key_jwk(
84    variant: EcdsaVariant,
85    jwk: impl Into<String>,
86    options: SigningKeyOptions,
87) -> Result<SigningKey, Error> {
88    Ok(SigningKey::from_raw(
89        bindings::ecdsa_sign::import_signing_key_jwk(variant, jwk.into(), options.lower()).await?,
90    ))
91}
92
93/// Mint a signing key from unwrapped key material read as a PKCS#8
94/// PrivateKeyInfo, subject to [`import_signing_key_pkcs8`]'s contract.
95/// Consumes the [`UnwrapInput`]; the minted key's usages and
96/// extractability come from `options` alone.
97pub async fn unwrap_signing_key_pkcs8(
98    variant: EcdsaVariant,
99    input: UnwrapInput,
100    options: SigningKeyOptions,
101) -> Result<SigningKey, Error> {
102    Ok(SigningKey::from_raw(
103        bindings::ecdsa_sign::unwrap_signing_key_pkcs8(variant, input.into_raw(), options.lower())
104            .await?,
105    ))
106}
107
108/// Mint a signing key from unwrapped key material read as an EC private
109/// JWK, subject to [`import_signing_key_jwk`]'s contract plus the
110/// unwrap-path `use`/`key_ops` checks (see the WIT `README.md`, "JWK
111/// contract"). Consumes the [`UnwrapInput`]; see
112/// [`unwrap_signing_key_pkcs8`] for the options model.
113pub async fn unwrap_signing_key_jwk(
114    variant: EcdsaVariant,
115    input: UnwrapInput,
116    options: SigningKeyOptions,
117) -> Result<SigningKey, Error> {
118    Ok(SigningKey::from_raw(
119        bindings::ecdsa_sign::unwrap_signing_key_jwk(variant, input.into_raw(), options.lower())
120            .await?,
121    ))
122}