Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e2a624e
Scaffold bouncycastle-rsa crate
dghgit Sep 19, 2026
11cdd23
rsa: constant-time modular exponentiation over a runtime modulus
dghgit Sep 19, 2026
d8802c2
rsa: CRT key types and RSASP1/RSAVP1 (RFC 8017 SS5.2)
dghgit Sep 19, 2026
34c635e
rsa: RSASSA-PKCS1-v1_5 sign/verify for RSA-2048/SHA-256
dghgit Sep 19, 2026
84ce30c
rsa: RSASSA-PSS sign/verify for RSA-2048/SHA-256
dghgit Sep 19, 2026
cb8c656
rsa: SHA-384 and SHA-512 for RSA-2048 (PKCS#1 v1.5 and PSS)
dghgit Sep 19, 2026
a5c65d6
rsa: RSA-1024, 1536, 3072, 4096, and 8192 (PKCS#1 v1.5 and PSS)
dghgit Sep 19, 2026
6cc1f19
rsa: RSASSA-PSS-SHAKE128/256 (RFC 8702 SS3.2.1)
dghgit Sep 19, 2026
1c3e0b7
rsa: CLI subcommands, criterion benches, and a stack-usage harness
dghgit Sep 19, 2026
d77e3b8
rsa: crate docs -- Usage Examples, Memory Usage, Security Considerations
dghgit Sep 19, 2026
9854cf9
rsa: fix test-coverage gaps found by the consolidated mutants run
dghgit Sep 19, 2026
05cb502
rsa: remove dead MontgomeryContext::modulus()
dghgit Sep 20, 2026
ef85b0d
rsa: hand the EMSA encoders/verifiers the message hash instead of the…
dghgit Sep 20, 2026
23934dc
rsa: implement bouncycastle_core's Signer/SignatureVerifier and Signa…
dghgit Sep 20, 2026
1ea8137
cli: rsa-* subcommands stream stdin through Signer/SignatureVerifier …
dghgit Sep 20, 2026
f392c99
rsa: drop the per-size free-function API now that every pairing is a …
dghgit Sep 21, 2026
07adb65
rsa: rename the key type aliases Rsa<N>PrivateKey/Rsa<N>PublicKey to …
dghgit Sep 21, 2026
9acece3
rsa: add key pair generation (FIPS 186-5 Appendix A.1.3) for RSA-2048…
dghgit Sep 21, 2026
12a2d4d
rsa: split the exponentiation out of rsavp1/rsasp1 into crate-private…
dghgit Sep 24, 2026
5d54169
rsa: add RSASVE (SP 800-56B Rev. 2 §7.2.1) as a KEM for RSA-2048/3072…
dghgit Sep 24, 2026
366bdd2
rsa: reject a signature representative more than 64 bits shorter than…
dghgit Oct 9, 2026
1093a90
Revert "rsa: reject a signature representative more than 64 bits shor…
dghgit Oct 10, 2026
649ba7a
rsa, cli: follow feature/ecdsa's do_ rename of the streaming Signer a…
dghgit Oct 11, 2026
1653bda
rsa, cli: port the signature schemes onto the key role traits
dghgit Nov 3, 2026
46a5103
rsa-sig: the merge-time adaptations to feature/key-rework-memory, car…
dghgit Nov 3, 2026
a582209
rsa-sig: the merge-time adaptations to release/0.1.3alpha, carried ov…
dghgit Nov 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ bouncycastle-mldsa = { path = "./crypto/mldsa" }
bouncycastle-mldsa-common = { path = "./crypto/mldsa-common" }
bouncycastle-mldsa-lowmemory = { path = "./crypto/mldsa-lowmemory" }
bouncycastle-rng = { path = "./crypto/rng" }
bouncycastle-rsa = { path = "./crypto/rsa" }
bouncycastle-sha2 = { path = "./crypto/sha2" }
bouncycastle-sha3 = { path = "./crypto/sha3" }
bouncycastle-sm2 = { path = "./crypto/sm2" }
Expand Down Expand Up @@ -76,6 +77,7 @@ bouncycastle-mldsa-lowmemory.workspace = true
bouncycastle-mlkem.workspace = true
bouncycastle-mlkem-lowmemory.workspace = true
bouncycastle-rng.workspace = true
bouncycastle-rsa.workspace = true
bouncycastle-sha2.workspace = true
bouncycastle-sha3.workspace = true
bouncycastle-sm2.workspace = true
Expand Down
298 changes: 298 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ mod mac_cmd;
mod mldsa_cmd;
mod mlkem_cmd;
mod rng_cmd;
mod rsa_cmd;
mod rsasve_cmd;
mod sha2_cmd;
mod sha3_cmd;
mod sm2_cmd;
Expand All @@ -26,6 +28,8 @@ use crate::hkdf_cmd::HKDFVariant;
use crate::mac_cmd::HMACVariant;
use crate::mldsa_cmd::{MLDSAAction, PreHashAlg};
use crate::rng_cmd::DrbgHash;
use crate::rsa_cmd::{RSAAction, RSAHash, RSAScheme};
use crate::rsasve_cmd::RSASVEAction;
use crate::sha2_cmd::SHA2Variant;
use crate::sha3_cmd::{SHA3Variant, Strength};
use crate::sm2_cmd::SM2Action;
Expand Down Expand Up @@ -2545,6 +2549,270 @@ enum Subcommands {
x: bool,
},

/// RSASVE over RSA-2048: the RSA KEM of SP 800-56B Rev. 2 SS7.2.1 (BC FIPS Java's KTS_SVE /
/// RSA-KAS-KEM, OpenSSL's "RSASVE" kem op). `keygen` (FIPS 186-5 A.1.3, e = 65537) writes the
/// private key to stdout and the public key to `--pkfile`; key files use the same raw encoding
/// as rsa-2048's. The shared secret is the raw 256-byte secret value Z, to be passed through a
/// KDF before use.
RSASVE_2048 {
action: RSASVEAction,

#[arg(long)]
/// The private key file (in hex or binary) for decaps
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for encaps, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The ciphertext value file (in hex or binary) either for encaps to output to, or for
/// decaps to read from.
ctfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSASVE over RSA-3072. See rsasve-2048.
RSASVE_3072 {
action: RSASVEAction,

#[arg(long)]
/// The private key file (in hex or binary) for decaps
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for encaps, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The ciphertext value file (in hex or binary) either for encaps to output to, or for
/// decaps to read from.
ctfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSASVE over RSA-4096. See rsasve-2048.
RSASVE_4096 {
action: RSASVEAction,

#[arg(long)]
/// The private key file (in hex or binary) for decaps
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for encaps, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The ciphertext value file (in hex or binary) either for encaps to output to, or for
/// decaps to read from.
ctfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSASVE over RSA-8192. See rsasve-2048.
RSASVE_8192 {
action: RSASVEAction,

#[arg(long)]
/// The private key file (in hex or binary) for decaps
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for encaps, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The ciphertext value file (in hex or binary) either for encaps to output to, or for
/// decaps to read from.
ctfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSA-1024 signature verification (RFC 8017 SS8.2), PKCS#1 v1.5 only. Verification-only: this
/// crate has no RSA-1024 private key type at all. See rsa-2048 for --scheme/--hash.
RSA_1024 {
#[arg(long, value_enum)]
/// The signature scheme: only `pkcs1v15` is available at this modulus size.
scheme: RSAScheme,

#[arg(long, value_enum)]
/// The message digest: `sha256` or `sha384` only at this modulus size.
hash: RSAHash,

#[arg(long)]
/// The public key file (in hex or binary) for verifying
pkfile: Option<String>,

#[arg(long)]
/// The signature value file (in hex or binary) for verifying
sigfile: Option<String>,
},

/// RSA-1536 signature verification (RFC 8017 SS8.2), PKCS#1 v1.5 only. Verification-only: this
/// crate has no RSA-1536 private key type at all. See rsa-2048 for --scheme/--hash.
RSA_1536 {
#[arg(long, value_enum)]
/// The signature scheme: only `pkcs1v15` is available at this modulus size.
scheme: RSAScheme,

#[arg(long, value_enum)]
/// The message digest: `sha256`, `sha384`, or `sha512` at this modulus size.
hash: RSAHash,

#[arg(long)]
/// The public key file (in hex or binary) for verifying
pkfile: Option<String>,

#[arg(long)]
/// The signature value file (in hex or binary) for verifying
sigfile: Option<String>,
},

/// RSA-2048 key generation, signing and verification: RSASSA-PKCS1-v1_5 (RFC 8017 SS8.2) or
/// RSASSA-PSS (RFC 8017 SS8.1, or RFC 8702 SS3.2.1 with `--hash shake128`), selected by
/// `--scheme`/`--hash`. PSS draws a fresh salt from the OS RNG each time it signs. `keygen`
/// (FIPS 186-5 A.1.3, e = 65537) writes the private key to stdout and the public key to
/// `--pkfile`. Private/public key files use this crate's own raw fixed-width encoding (see
/// `RsaPrivateKey`/`RsaPublicKey`'s `# Encoding` docs), not PEM or ASN.1 DER.
RSA_2048 {
action: RSAAction,

#[arg(long, value_enum)]
/// The signature scheme.
scheme: RSAScheme,

#[arg(long, value_enum)]
/// The message digest: `sha256`, `sha384`, `sha512`, or (PSS only) `shake128`.
hash: RSAHash,

#[arg(long)]
/// The private key file (in hex or binary) for signing
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for verifying, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The signature value file (in hex or binary) for verifying
sigfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSA-3072 signing/verification. See rsa-2048.
RSA_3072 {
action: RSAAction,

#[arg(long, value_enum)]
/// The signature scheme.
scheme: RSAScheme,

#[arg(long, value_enum)]
/// The message digest: `sha256`, `sha384`, `sha512`, or (PSS only) `shake128`.
hash: RSAHash,

#[arg(long)]
/// The private key file (in hex or binary) for signing
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for verifying, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The signature value file (in hex or binary) for verifying
sigfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSA-4096 signing/verification. See rsa-2048; note `--hash shake256` (not shake128) is the
/// SHAKE choice wired up at this modulus size (RFC 8702 SS5).
RSA_4096 {
action: RSAAction,

#[arg(long, value_enum)]
/// The signature scheme.
scheme: RSAScheme,

#[arg(long, value_enum)]
/// The message digest: `sha256`, `sha384`, `sha512`, or (PSS only) `shake256`.
hash: RSAHash,

#[arg(long)]
/// The private key file (in hex or binary) for signing
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for verifying, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The signature value file (in hex or binary) for verifying
sigfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// RSA-8192 signing/verification. See rsa-2048; no PSS-SHAKE variant is wired up at this
/// modulus size (no Wycheproof vectors exist for it, and RFC 8702 SS5's "4096-bit or larger"
/// SHAKE256 recommendation is already covered by rsa-4096).
RSA_8192 {
action: RSAAction,

#[arg(long, value_enum)]
/// The signature scheme.
scheme: RSAScheme,

#[arg(long, value_enum)]
/// The message digest: `sha256`, `sha384`, or `sha512`.
hash: RSAHash,

#[arg(long)]
/// The private key file (in hex or binary) for signing
skfile: Option<String>,

#[arg(long)]
/// The public key file (in hex or binary) for verifying, or to write the generated public
/// key to for keygen
pkfile: Option<String>,

#[arg(long)]
/// The signature value file (in hex or binary) for verifying
sigfile: Option<String>,

#[arg(short)]
/// Output in hex format.
x: bool,
},

/// The SM2 Digital Signature Algorithm (GB/T 32918.2-2016; draft-shen-sm2-ecdsa-02 S5),
/// randomised only (the standard specifies no deterministic scheme). `--idfile` is mandatory
/// for signing and verifying: it carries the signer's identity IDA (S5.5), which every SM2
Expand Down Expand Up @@ -3174,6 +3442,36 @@ fn run() {
Some(Subcommands::SHAKE256 { length, x }) => {
sha3_cmd::shake_cmd(Strength::Bits256, *length, *x);
}
Some(Subcommands::RSASVE_2048 { action, skfile, pkfile, ctfile, x }) => {
rsasve_cmd::rsasve_2048_cmd(action, skfile, pkfile, ctfile, *x);
}
Some(Subcommands::RSASVE_3072 { action, skfile, pkfile, ctfile, x }) => {
rsasve_cmd::rsasve_3072_cmd(action, skfile, pkfile, ctfile, *x);
}
Some(Subcommands::RSASVE_4096 { action, skfile, pkfile, ctfile, x }) => {
rsasve_cmd::rsasve_4096_cmd(action, skfile, pkfile, ctfile, *x);
}
Some(Subcommands::RSASVE_8192 { action, skfile, pkfile, ctfile, x }) => {
rsasve_cmd::rsasve_8192_cmd(action, skfile, pkfile, ctfile, *x);
}
Some(Subcommands::RSA_1024 { scheme, hash, pkfile, sigfile }) => {
rsa_cmd::rsa_1024_cmd(scheme, hash, pkfile, sigfile);
}
Some(Subcommands::RSA_1536 { scheme, hash, pkfile, sigfile }) => {
rsa_cmd::rsa_1536_cmd(scheme, hash, pkfile, sigfile);
}
Some(Subcommands::RSA_2048 { action, scheme, hash, skfile, pkfile, sigfile, x }) => {
rsa_cmd::rsa_2048_cmd(action, scheme, hash, skfile, pkfile, sigfile, *x);
}
Some(Subcommands::RSA_3072 { action, scheme, hash, skfile, pkfile, sigfile, x }) => {
rsa_cmd::rsa_3072_cmd(action, scheme, hash, skfile, pkfile, sigfile, *x);
}
Some(Subcommands::RSA_4096 { action, scheme, hash, skfile, pkfile, sigfile, x }) => {
rsa_cmd::rsa_4096_cmd(action, scheme, hash, skfile, pkfile, sigfile, *x);
}
Some(Subcommands::RSA_8192 { action, scheme, hash, skfile, pkfile, sigfile, x }) => {
rsa_cmd::rsa_8192_cmd(action, scheme, hash, skfile, pkfile, sigfile, *x);
}
Some(Subcommands::SM2 { action, idfile, skfile, pkfile, sigfile, x }) => {
sm2_cmd::sm2_cmd(action, idfile, skfile, pkfile, sigfile, *x);
}
Expand Down
Loading
Loading