| Crates.io | sad-rsa |
| lib.rs | sad-rsa |
| version | 0.1.1 |
| created_at | 2026-01-16 22:55:56.460887+00 |
| updated_at | 2026-01-20 05:03:09.304993+00 |
| description | Hardened pure Rust RSA implementation with Marvin attack mitigation |
| homepage | |
| repository | https://github.com/sadco-io/sad-rsa |
| max_upload_size | |
| id | 2049443 |
| size | 405,714 |
A hardened pure Rust RSA implementation with protection against timing side-channel attacks.
This is a security-focused fork of the RustCrypto RSA crate that implements implicit rejection for PKCS#1 v1.5 decryption to mitigate the Marvin Attack (RUSTSEC-2023-0071).
| Feature | sad-rsa | upstream rsa |
|---|---|---|
| Marvin Attack mitigation | Yes | No |
| Implicit rejection (PKCS#1 v1.5) | Default | Not implemented |
| RFC 8017 length validation | Yes | Partial |
| Key material zeroization | Enhanced | Basic |
Instead of returning distinguishable errors for invalid PKCS#1 v1.5 padding, this crate returns a deterministic pseudo-random message derived from the ciphertext. This makes valid and invalid ciphertexts indistinguishable to attackers, preventing padding oracle attacks.
Implementation follows draft-irtf-cfrg-rsa-guidance-04.
Replace rsa with sad-rsa in your Cargo.toml:
[dependencies]
sad-rsa = "0.1"
The API is fully compatible with the upstream rsa crate:
use sad_rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
let mut rng = rand::thread_rng();
let bits = 2048;
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pub_key = RsaPublicKey::from(&priv_key);
// Encrypt
let data = b"hello world";
let enc_data = pub_key.encrypt(&mut rng, Pkcs1v15Encrypt, &data[..]).expect("failed to encrypt");
assert_ne!(&data[..], &enc_data[..]);
// Decrypt - now protected against Marvin attack
let dec_data = priv_key.decrypt(Pkcs1v15Encrypt, &enc_data).expect("failed to decrypt");
assert_eq!(&data[..], &dec_data[..]);
rsarsa with sad-rsa in Cargo.tomluse rsa:: with use sad_rsa:: in your codeNote: Invalid ciphertexts will now return synthetic messages instead of errors. If your code explicitly checks for decryption errors to detect tampering, you should use authenticated encryption (e.g., RSA-OAEP or hybrid encryption with AES-GCM) instead.
Note: Key generation is much faster when building with higher optimization levels:
[profile.dev] opt-level = 2
This crate supports Rust 1.85 or higher.
This crate is a fork of the excellent RustCrypto RSA crate. We are grateful to the RustCrypto developers for their foundational work.
See the NOTICE file for full attribution details.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.