polymorph_webcrypto_guest/rsa_pss.rs
1//! `rsa-pss-verify` key creation (RFC 8017 §8.1), plus — behind the
2//! `rsa-sign` cargo feature — `rsa-pss-sign`.
3
4use crate::{bindings, Error, VerifyingKey};
5#[cfg(feature = "rsa-sign")]
6use crate::{SigningKey, SigningKeyOptions};
7
8pub use crate::bindings::rsa_pss_verify::RsaVariant;
9
10#[cfg(feature = "rsa-sign")]
11pub use crate::bindings::rsa_pss_sign::RsaModulus;
12
13/// Import a public key as an X.509 SubjectPublicKeyInfo (DER). The
14/// declared variant binds the digest at mint, and `salt_length` — the PSS
15/// salt length in bytes — binds there too: the minted key verifies exactly
16/// one PSS parameterization, and a signature made under any other salt
17/// length fails [`Error::AuthenticationFailed`]. Admission follows the RSA
18/// family contract (see the WIT `rsa` interface).
19pub async fn import_verifying_key_spki(
20 variant: RsaVariant,
21 salt_length: u32,
22 spki: impl Into<Vec<u8>>,
23) -> Result<VerifyingKey, Error> {
24 Ok(VerifyingKey::from_raw(
25 bindings::rsa_pss_verify::import_verifying_key_spki(variant, salt_length, spki.into())
26 .await?,
27 ))
28}
29
30/// Import a public key as an RSA public JWK (`kty: "RSA"`, with `n` and
31/// `e`, as JSON text); see [`import_verifying_key_spki`] for
32/// `salt_length`. An `alg` member, when present, must be the variant's
33/// JOSE alg (`"PS256"`, `"PS384"`, or `"PS512"`). See the WIT
34/// `mac-key.export-key-jwk` doc for the package-wide JWK contract.
35pub async fn import_verifying_key_jwk(
36 variant: RsaVariant,
37 salt_length: u32,
38 jwk: impl Into<String>,
39) -> Result<VerifyingKey, Error> {
40 Ok(VerifyingKey::from_raw(
41 bindings::rsa_pss_verify::import_verifying_key_jwk(variant, salt_length, jwk.into())
42 .await?,
43 ))
44}
45
46/// Generate a fresh signing key pair of the declared variant and modulus
47/// length, returning both halves. The public exponent is 65537; it is
48/// not a parameter. Keys minted here sign with the salt length equal to
49/// the digest length (the JOSE `PS*` profile); it is not a parameter
50/// either.
51#[cfg(feature = "rsa-sign")]
52pub async fn generate_key(
53 variant: RsaVariant,
54 modulus: RsaModulus,
55 options: SigningKeyOptions,
56) -> Result<(SigningKey, VerifyingKey), Error> {
57 let (signing, verifying) =
58 bindings::rsa_pss_sign::generate_key(variant, modulus, options.lower()).await?;
59 Ok((
60 SigningKey::from_raw(signing),
61 VerifyingKey::from_raw(verifying),
62 ))
63}
64
65/// Import a signing key as a PKCS#8 PrivateKeyInfo (DER, with the CRT
66/// parameters). Admission follows the RSA family contract plus the
67/// signing window — a 2048–8192-bit modulus (see the WIT `rsa-pss-sign`
68/// interface). Returns only the signing key; supply the public half to
69/// [`import_verifying_key_spki`] if you need it.
70#[cfg(feature = "rsa-sign")]
71pub async fn import_signing_key_pkcs8(
72 variant: RsaVariant,
73 pkcs8: impl Into<Vec<u8>>,
74 options: SigningKeyOptions,
75) -> Result<SigningKey, Error> {
76 Ok(SigningKey::from_raw(
77 bindings::rsa_pss_sign::import_signing_key_pkcs8(variant, pkcs8.into(), options.lower())
78 .await?,
79 ))
80}
81
82/// Import a signing key as an RSA private JWK (`kty: "RSA"`, with `n`,
83/// `e`, `d`, and the CRT members, as JSON text), subject to
84/// [`import_signing_key_pkcs8`]'s admission. An `alg` member, when
85/// present, must be the variant's JOSE alg (`"PS256"`, `"PS384"`, or
86/// `"PS512"`).
87#[cfg(feature = "rsa-sign")]
88pub async fn import_signing_key_jwk(
89 variant: RsaVariant,
90 jwk: impl Into<String>,
91 options: SigningKeyOptions,
92) -> Result<SigningKey, Error> {
93 Ok(SigningKey::from_raw(
94 bindings::rsa_pss_sign::import_signing_key_jwk(variant, jwk.into(), options.lower())
95 .await?,
96 ))
97}