Skip to main content

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}