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