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}