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
c7f49ee
Scaffold bouncycastle-rsa crate
dghgit Sep 19, 2026
5b4e8fd
rsa: constant-time modular exponentiation over a runtime modulus
dghgit Sep 19, 2026
cd4fbde
rsa: CRT key types and RSASP1/RSAVP1 (RFC 8017 SS5.2)
dghgit Sep 19, 2026
1ef9672
rsa: RSASSA-PKCS1-v1_5 sign/verify for RSA-2048/SHA-256
dghgit Sep 19, 2026
f091a86
rsa: RSASSA-PSS sign/verify for RSA-2048/SHA-256
dghgit Sep 19, 2026
3395a8b
rsa: SHA-384 and SHA-512 for RSA-2048 (PKCS#1 v1.5 and PSS)
dghgit Sep 19, 2026
9a321d1
rsa: RSA-1024, 1536, 3072, 4096, and 8192 (PKCS#1 v1.5 and PSS)
dghgit Sep 19, 2026
f6177a4
rsa: RSASSA-PSS-SHAKE128/256 (RFC 8702 SS3.2.1)
dghgit Sep 19, 2026
78f6bc5
rsa: CLI subcommands, criterion benches, and a stack-usage harness
dghgit Sep 19, 2026
07bf49c
rsa: crate docs -- Usage Examples, Memory Usage, Security Considerations
dghgit Sep 19, 2026
3d0bab3
rsa: fix test-coverage gaps found by the consolidated mutants run
dghgit Sep 19, 2026
a738cdd
rsa: remove dead MontgomeryContext::modulus()
dghgit Sep 20, 2026
b17fa6c
rsa: hand the EMSA encoders/verifiers the message hash instead of the…
dghgit Sep 20, 2026
ab40a78
rsa: implement bouncycastle_core's Signer/SignatureVerifier and Signa…
dghgit Sep 20, 2026
70c7a78
cli: rsa-* subcommands stream stdin through Signer/SignatureVerifier …
dghgit Sep 20, 2026
5add8b0
rsa: drop the per-size free-function API now that every pairing is a …
dghgit Sep 21, 2026
4e4056b
rsa: rename the key type aliases Rsa<N>PrivateKey/Rsa<N>PublicKey to …
dghgit Sep 21, 2026
00209d2
rsa: add key pair generation (FIPS 186-5 Appendix A.1.3) for RSA-2048…
dghgit Sep 21, 2026
ffeb6e7
rsa: split the exponentiation out of rsavp1/rsasp1 into crate-private…
dghgit Sep 24, 2026
41f62fc
rsa: add RSASVE (SP 800-56B Rev. 2 §7.2.1) as a KEM for RSA-2048/3072…
dghgit Sep 24, 2026
4479d20
Merge branch 'feature/ecdsa' into feature/rsa-sig
dghgit Sep 29, 2026
c5db115
Merge branch 'feature/ecdsa' into feature/rsa-sig
dghgit Sep 30, 2026
d5f1367
rsa: reject a signature representative more than 64 bits shorter than…
dghgit Oct 9, 2026
5819678
Revert "rsa: reject a signature representative more than 64 bits shor…
dghgit Oct 10, 2026
ed9f64f
Merge branch 'feature/ecdsa' into feature/rsa-sig
dghgit Oct 11, 2026
29eefaf
rsa, cli: follow feature/ecdsa's do_ rename of the streaming Signer a…
dghgit Oct 11, 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 @@ -28,6 +28,7 @@ bouncycastle-mlkem-lowmemory = { path = "./crypto/mlkem-lowmemory" }
bouncycastle-mldsa = { path = "./crypto/mldsa" }
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 @@ -65,6 +66,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 @@ -14,6 +14,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 @@ -22,6 +24,8 @@ mod sm3_cmd;
use crate::ecdsa_cmd::ECDSAAction;
use crate::mac_cmd::HMACVariant;
use crate::mldsa_cmd::MLDSAAction;
use crate::rsa_cmd::{RSAAction, RSAHash, RSAScheme};
use crate::rsasve_cmd::RSASVEAction;
use crate::sha2_cmd::SHA2Variant;
use crate::sm2_cmd::SM2Action;
use clap::{Parser, Subcommand};
Expand Down Expand Up @@ -1697,6 +1701,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 (draft-shen-sm2-ecdsa-02 S5, GB/T 32918.2-2016),
/// randomised only (the draft specifies no deterministic scheme). `--idfile` is mandatory for
/// signing and verifying: it carries the signer's identity IDA, which every SM2 operation
Expand Down Expand Up @@ -2018,6 +2286,36 @@ fn run() {
Some(Subcommands::ECDSA_BP512R1 { action, skfile, pkfile, sigfile, x }) => {
ecdsa_cmd::ecdsa_bp512r1_cmd(action, skfile, pkfile, sigfile, *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