rsa/lib.rs
1#![cfg_attr(not(test), no_std)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(not(all(feature = "alloc", feature = "private-key")), allow(unused))]
4#![doc = include_str!("../README.md")]
5#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
6#![warn(missing_docs)]
7#![cfg_attr(not(test), deny(clippy::unwrap_used))]
8
9//! # Supported algorithms
10//!
11//! This crate supports several schemes described in [RFC8017]:
12//!
13//! - [OAEP encryption scheme](#oaep-encryption)
14//! - [PKCS#1 v1.5 encryption scheme](#pkcs1-v15-encryption)
15//! - [PKCS#1 v1.5 signature scheme](#pkcs1-v15-signatures)
16//! - [PSS signature scheme](#pss-signatures)
17//!
18//! These schemes are described below.
19//!
20//! # Usage
21//!
22//! ## OAEP encryption
23//!
24//! Note: requires `sha2` feature of `rsa` crate is enabled.
25//!
26#![cfg_attr(feature = "sha2", doc = "```")]
27#![cfg_attr(not(feature = "sha2"), doc = "```ignore")]
28//! use rsa::{RsaPrivateKey, RsaPublicKey, Oaep, sha2::Sha256};
29//!
30//! let mut rng = rand::rng();
31//!
32//! let bits = 2048;
33//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
34//! let public_key = RsaPublicKey::from(&private_key);
35//!
36//! // Encrypt
37//! let data = b"hello world";
38//! let padding = Oaep::<Sha256>::new();
39//! let enc_data = public_key.encrypt(&mut rng, padding, &data[..]).expect("failed to encrypt");
40//! assert_ne!(&data[..], &enc_data[..]);
41//!
42//! // Decrypt
43//! let padding = Oaep::<Sha256>::new();
44//! let dec_data = private_key.decrypt(padding, &enc_data).expect("failed to decrypt");
45//! assert_eq!(&data[..], &dec_data[..]);
46//! ```
47//!
48//! ## PKCS#1 v1.5 encryption
49//!
50//! <div class="warning">
51//! <b>Warning:</b>
52//! See security notes in the <code><a href="./pkcs1v15/index.html">pkcs1v15</a></code> module.
53//! </div>
54//!
55#![cfg_attr(feature = "private-key", doc = "```")]
56#![cfg_attr(not(feature = "private-key"), doc = "```ignore")]
57//! use rsa::{RsaPrivateKey, RsaPublicKey, Pkcs1v15Encrypt};
58//!
59//! let mut rng = rand::rng();
60//!
61//! let bits = 2048;
62//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
63//! let public_key = RsaPublicKey::from(&private_key);
64//!
65//! // Encrypt
66//! let data = b"hello world";
67//! let enc_data = public_key.encrypt(&mut rng, Pkcs1v15Encrypt, &data[..]).expect("failed to encrypt");
68//! assert_ne!(&data[..], &enc_data[..]);
69//!
70//! // Decrypt
71//! let dec_data = private_key.decrypt(Pkcs1v15Encrypt, &enc_data).expect("failed to decrypt");
72//! assert_eq!(&data[..], &dec_data[..]);
73//! ```
74//!
75//! ## PKCS#1 v1.5 signatures
76//!
77//! <div class="warning">
78//! <b>Warning:</b>
79//! See security notes in the <code><a href="./pkcs1v15/index.html">pkcs1v15</a></code> module.
80//! </div>
81//!
82//! Note: requires `sha2` feature of `rsa` crate is enabled.
83//!
84#![cfg_attr(feature = "sha2", doc = "```")]
85#![cfg_attr(not(feature = "sha2"), doc = "```ignore")]
86//! use rsa::RsaPrivateKey;
87//! use rsa::pkcs1v15::{SigningKey, VerifyingKey};
88//! use rsa::signature::{Keypair, RandomizedSigner, SignatureEncoding, Verifier};
89//! use rsa::sha2::{Digest, Sha256};
90//!
91//! let mut rng = rand::rng();
92//!
93//! let bits = 2048;
94//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
95//! let signing_key = SigningKey::<Sha256>::new(private_key);
96//! let verifying_key = signing_key.verifying_key();
97//!
98//! // Sign
99//! let data = b"hello world";
100//! let signature = signing_key.sign_with_rng(&mut rng, data);
101//! assert_ne!(signature.to_bytes().as_ref(), data.as_slice());
102//!
103//! // Verify
104//! verifying_key.verify(data, &signature).expect("failed to verify");
105//! ```
106//!
107//! ## PSS signatures
108//!
109//! Note: requires `sha2` feature of `rsa` crate is enabled.
110//!
111#![cfg_attr(feature = "sha2", doc = "```")]
112#![cfg_attr(not(feature = "sha2"), doc = "```ignore")]
113//! use rsa::RsaPrivateKey;
114//! use rsa::pss::{BlindedSigningKey, VerifyingKey};
115//! use rsa::signature::{Keypair,RandomizedSigner, SignatureEncoding, Verifier};
116//! use rsa::sha2::{Digest, Sha256};
117//!
118//! let mut rng = rand::rng();
119//!
120//! let bits = 2048;
121//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
122//! let signing_key = BlindedSigningKey::<Sha256>::new(private_key);
123//! let verifying_key = signing_key.verifying_key();
124//!
125//! // Sign
126//! let data = b"hello world";
127//! let signature = signing_key.sign_with_rng(&mut rng, data);
128//! assert_ne!(signature.to_bytes().as_ref(), data);
129//!
130//! // Verify
131//! verifying_key.verify(data, &signature).expect("failed to verify");
132//! ```
133//!
134//! ## PKCS#1 RSA Key Encoding
135//!
136//! PKCS#1 supports a legacy format for encoding RSA keys as binary (DER) or
137//! text (PEM) data.
138//!
139//! You can recognize PEM encoded PKCS#1 keys because they have "RSA * KEY" in
140//! the type label, e.g.:
141//!
142//! ```text
143//! -----BEGIN RSA PRIVATE KEY-----
144//! ```
145//!
146//! Most modern applications use the newer PKCS#8 format instead (see below).
147//!
148//! The following traits can be used to decode/encode [`RsaPrivateKey`] and
149//! [`RsaPublicKey`] as PKCS#1. Note that [`pkcs1`] is re-exported from the
150//! toplevel of the `rsa` crate:
151//!
152//! - [`pkcs1::DecodeRsaPrivateKey`]: decode RSA private keys from PKCS#1
153//! - [`pkcs1::EncodeRsaPrivateKey`]: encode RSA private keys to PKCS#1
154//! - [`pkcs1::DecodeRsaPublicKey`]: decode RSA public keys from PKCS#1
155//! - [`pkcs1::EncodeRsaPublicKey`]: encode RSA public keys to PKCS#1
156//!
157//! ### Example
158//!
159//! ```
160//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
161//! # #[cfg(all(feature = "encoding", feature = "std"))]
162//! # {
163//! use rsa::{RsaPublicKey, pkcs1::DecodeRsaPublicKey};
164//!
165//! let pem = "-----BEGIN RSA PUBLIC KEY-----
166//! MIIBCgKCAQEAtsQsUV8QpqrygsY+2+JCQ6Fw8/omM71IM2N/R8pPbzbgOl0p78MZ
167//! GsgPOQ2HSznjD0FPzsH8oO2B5Uftws04LHb2HJAYlz25+lN5cqfHAfa3fgmC38Ff
168//! wBkn7l582UtPWZ/wcBOnyCgb3yLcvJrXyrt8QxHJgvWO23ITrUVYszImbXQ67YGS
169//! 0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0NfFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J
170//! 9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejIn04APPKIjpMyQdnWlby7rNyQtE4+CV+j
171//! cFjqJbE/Xilcvqxt6DirjFCvYeKYl1uHLwIDAQAB
172//! -----END RSA PUBLIC KEY-----";
173//!
174//! let public_key = RsaPublicKey::from_pkcs1_pem(pem)?;
175//! # }
176//! # Ok(())
177//! # }
178//! ```
179//!
180//! ## PKCS#8 RSA Key Encoding
181//!
182//! PKCS#8 is a private key format with support for multiple algorithms.
183//! Like PKCS#1, it can be encoded as binary (DER) or text (PEM).
184//!
185//! You can recognize PEM encoded PKCS#8 keys because they *don't* have
186//! an algorithm name in the type label, e.g.:
187//!
188//! ```text
189//! -----BEGIN PRIVATE KEY-----
190//! ```
191//!
192//! The following traits can be used to decode/encode [`RsaPrivateKey`] and
193//! [`RsaPublicKey`] as PKCS#8. Note that [`pkcs8`] is re-exported from the
194//! toplevel of the `rsa` crate:
195//!
196//! - [`pkcs8::DecodePrivateKey`]: decode private keys from PKCS#8
197//! - [`pkcs8::EncodePrivateKey`]: encode private keys to PKCS#8
198//! - [`pkcs8::DecodePublicKey`]: decode public keys from PKCS#8
199//! - [`pkcs8::EncodePublicKey`]: encode public keys to PKCS#8
200//!
201//! ### Example
202//!
203//! ```
204//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
205//! # #[cfg(all(feature = "encoding", feature = "std"))]
206//! # {
207//! use rsa::{RsaPublicKey, pkcs8::DecodePublicKey};
208//!
209//! let pem = "-----BEGIN PUBLIC KEY-----
210//! MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtsQsUV8QpqrygsY+2+JC
211//! Q6Fw8/omM71IM2N/R8pPbzbgOl0p78MZGsgPOQ2HSznjD0FPzsH8oO2B5Uftws04
212//! LHb2HJAYlz25+lN5cqfHAfa3fgmC38FfwBkn7l582UtPWZ/wcBOnyCgb3yLcvJrX
213//! yrt8QxHJgvWO23ITrUVYszImbXQ67YGS0YhMrbixRzmo2tpm3JcIBtnHrEUMsT0N
214//! fFdfsZhTT8YbxBvA8FdODgEwx7u/vf3J9qbi4+Kv8cvqyJuleIRSjVXPsIMnoejI
215//! n04APPKIjpMyQdnWlby7rNyQtE4+CV+jcFjqJbE/Xilcvqxt6DirjFCvYeKYl1uH
216//! LwIDAQAB
217//! -----END PUBLIC KEY-----";
218//!
219//! let public_key = RsaPublicKey::from_public_key_pem(pem)?;
220//! # }
221//! # Ok(())
222//! # }
223//! ```
224//!
225//! [RFC8017]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.1
226//!
227// TODO(tarcieri): figure out why rustdoc isn't rendering these links correctly
228//! [`pkcs8::DecodePublicKey`]: https://docs.rs/pkcs8/latest/pkcs8/trait.DecodePublicKey.html
229//! [`pkcs8::EncodePublicKey`]: https://docs.rs/pkcs8/latest/pkcs8/trait.EncodePublicKey.html
230
231#[cfg(doctest)]
232pub struct ReadmeDoctests;
233
234#[cfg(feature = "alloc")]
235#[macro_use]
236extern crate alloc;
237#[cfg(feature = "std")]
238extern crate std;
239
240#[cfg(feature = "alloc")]
241pub use crypto_bigint::BoxedUint;
242pub use rand_core;
243pub use signature;
244
245mod algorithms;
246pub mod errors;
247pub mod oaep;
248pub mod pkcs1v15;
249pub mod pss;
250pub mod traits;
251
252mod dummy_rng;
253mod encoding;
254mod key;
255#[cfg(feature = "modmath")]
256pub mod modmath_support;
257
258#[cfg(feature = "modmath")]
259pub use crate::modmath_support::{
260 ModMathForm, ModMathInt, ModMathIntCt, ModMathParams, ModMathValue,
261};
262#[cfg(feature = "modmath")]
263pub use fixed_bigint::{Ct, Nct};
264#[cfg(feature = "encoding")]
265pub use pkcs1;
266#[cfg(feature = "encoding")]
267pub use pkcs8;
268#[cfg(feature = "sha2")]
269pub use sha2;
270
271#[cfg(feature = "alloc")]
272pub use crate::key::RsaPublicKey;
273#[cfg(all(feature = "alloc", feature = "private-key"))]
274pub use crate::traits::keys::CrtValue;
275pub use crate::{
276 errors::{Error, Result},
277 key::GenericRsaPublicKey,
278 pkcs1v15::{Pkcs1v15Encrypt, Pkcs1v15Sign},
279};
280
281#[cfg(feature = "private-key")]
282pub use crate::key::RsaPrivateKey;
283
284#[cfg(feature = "alloc")]
285pub use crate::oaep::Oaep;
286#[cfg(feature = "alloc")]
287pub use crate::pss::Pss;
288
289#[cfg(all(feature = "hazmat", feature = "alloc"))]
290pub mod hazmat;