Skip to main content

polymorph_webcrypto_guest/
rsa_oaep.rs

1//! `rsa-oaep-encrypt` key creation (RFC 8017 §7.1) — the public half of
2//! key transport — plus, behind the `rsa-oaep-decrypt` cargo feature,
3//! `rsa-oaep-decrypt`.
4//!
5//! The declared variant binds the digest at mint; the MGF1 digest is the
6//! same digest. Admission tightens the RSA family contract on both ends:
7//! the modulus must be 2048–8192 bits (see the WIT `rsa-oaep-encrypt`
8//! interface). The plaintext bound follows from the mint: modulus bytes
9//! minus twice the digest length minus 2.
10
11use crate::{bindings, EncryptionKey, Error};
12#[cfg(feature = "rsa-oaep-decrypt")]
13use crate::{DecryptionKey, DecryptionKeyOptions};
14
15pub use crate::bindings::rsa_oaep_encrypt::RsaVariant;
16
17#[cfg(feature = "rsa-oaep-decrypt")]
18pub use crate::bindings::rsa_oaep_decrypt::RsaModulus;
19
20/// Import a public key as an X.509 SubjectPublicKeyInfo (DER). Admission
21/// follows the RSA family contract (see the WIT `rsa` interface) plus the
22/// 2048–8192-bit window.
23pub async fn import_encryption_key_spki(
24    variant: RsaVariant,
25    spki: impl Into<Vec<u8>>,
26) -> Result<EncryptionKey, Error> {
27    Ok(EncryptionKey::from_raw(
28        bindings::rsa_oaep_encrypt::import_encryption_key_spki(variant, spki.into()).await?,
29    ))
30}
31
32/// Import a public key as an RSA public JWK (`kty: "RSA"`, with `n` and
33/// `e`, as JSON text). An `alg` member, when present, must be the
34/// variant's JOSE alg (`"RSA-OAEP-256"`, `"RSA-OAEP-384"`, or
35/// `"RSA-OAEP-512"`). See the WIT `mac-key.export-key-jwk` doc for the
36/// package-wide JWK contract.
37pub async fn import_encryption_key_jwk(
38    variant: RsaVariant,
39    jwk: impl Into<String>,
40) -> Result<EncryptionKey, Error> {
41    Ok(EncryptionKey::from_raw(
42        bindings::rsa_oaep_encrypt::import_encryption_key_jwk(variant, jwk.into()).await?,
43    ))
44}
45
46/// Generate a fresh key pair of the declared variant and modulus length,
47/// returning both halves. The public exponent is 65537; it is not a
48/// parameter.
49#[cfg(feature = "rsa-oaep-decrypt")]
50pub async fn generate_key(
51    variant: RsaVariant,
52    modulus: RsaModulus,
53    options: DecryptionKeyOptions,
54) -> Result<(DecryptionKey, EncryptionKey), Error> {
55    let (decryption, encryption) =
56        bindings::rsa_oaep_decrypt::generate_key(variant, modulus, options.lower()).await?;
57    Ok((
58        DecryptionKey::from_raw(decryption),
59        EncryptionKey::from_raw(encryption),
60    ))
61}
62
63/// Import a decryption key as a PKCS#8 PrivateKeyInfo (DER, with the CRT
64/// parameters). Admission follows the RSA family contract plus the
65/// 2048–8192-bit window (see the WIT `rsa-oaep-decrypt` interface).
66/// Returns only the decryption key; supply the public half to
67/// [`import_encryption_key_spki`] if you need it.
68#[cfg(feature = "rsa-oaep-decrypt")]
69pub async fn import_decryption_key_pkcs8(
70    variant: RsaVariant,
71    pkcs8: impl Into<Vec<u8>>,
72    options: DecryptionKeyOptions,
73) -> Result<DecryptionKey, Error> {
74    Ok(DecryptionKey::from_raw(
75        bindings::rsa_oaep_decrypt::import_decryption_key_pkcs8(
76            variant,
77            pkcs8.into(),
78            options.lower(),
79        )
80        .await?,
81    ))
82}
83
84/// Import a decryption key as a full-CRT RSA private JWK (`kty: "RSA"`,
85/// with `n`, `e`, `d`, and the CRT members, as JSON text), subject to
86/// [`import_decryption_key_pkcs8`]'s admission. An `alg` member, when
87/// present, must be the variant's JOSE alg (`"RSA-OAEP-256"`,
88/// `"RSA-OAEP-384"`, or `"RSA-OAEP-512"`).
89#[cfg(feature = "rsa-oaep-decrypt")]
90pub async fn import_decryption_key_jwk(
91    variant: RsaVariant,
92    jwk: impl Into<String>,
93    options: DecryptionKeyOptions,
94) -> Result<DecryptionKey, Error> {
95    Ok(DecryptionKey::from_raw(
96        bindings::rsa_oaep_decrypt::import_decryption_key_jwk(variant, jwk.into(), options.lower())
97            .await?,
98    ))
99}