blob: 0f22d9f0e5d6d67f41421ccdb937eef07e0ba59a [file] [log] [blame] [edit]
// Copyright 2024 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! RSA signatures.
//!
//! New protocols should not use RSA, but it's still often found in existing
//! protocols. This module implements PKCS#1 signatures (the most common type).
//!
//! Creating a signature:
//!
//! ```
//! use bssl_crypto::{digest, rsa};
//! # use bssl_crypto::rsa::TEST_PKCS8_BYTES;
//!
//! // Generating an RSA private key is slow, so this examples parses it from
//! // PKCS#8 DER.
//! let private_key = rsa::PrivateKey::from_der_private_key_info(TEST_PKCS8_BYTES).unwrap();
//! let signed_msg = b"hello world";
//! let sig = private_key.sign_pkcs1::<digest::Sha256>(signed_msg);
//! ```
//!
//! To verify a signature, publish your _public_ key:
//!
//! ```
//! # use bssl_crypto::{rsa};
//! # use bssl_crypto::rsa::TEST_PKCS8_BYTES;
//! # let private_key = rsa::PrivateKey::from_der_private_key_info(TEST_PKCS8_BYTES).unwrap();
//! let public_key_bytes = private_key.as_public().to_der_subject_public_key_info();
//! ```
//!
//! Then verify the signature from above with it:
//!
//! ```
//! # use bssl_crypto::{digest, rsa};
//! # use bssl_crypto::rsa::TEST_PKCS8_BYTES;
//! # let private_key = rsa::PrivateKey::from_der_private_key_info(TEST_PKCS8_BYTES).unwrap();
//! # let signed_msg = b"hello world";
//! # let mut sig = private_key.sign_pkcs1::<digest::Sha256>(signed_msg);
//! # let public_key_bytes = private_key.as_public().to_der_subject_public_key_info();
//! let public_key = rsa::PublicKey::from_der_subject_public_key_info(public_key_bytes.as_ref())
//! .unwrap();
//! assert!(public_key.verify_pkcs1::<digest::Sha256>(signed_msg, sig.as_slice()).is_ok());
//! sig[0] ^= 1;
//! assert!(public_key.verify_pkcs1::<digest::Sha256>(signed_msg, sig.as_slice()).is_err());
//! ```
use crate::{
cbb_to_buffer, digest, parse_with_cbs, scoped, sealed, with_output_vec, Buffer, FfiSlice,
ForeignTypeRef, InvalidSignatureError,
};
use alloc::vec::Vec;
use core::ptr::null_mut;
/// An RSA public key.
pub struct PublicKey(*mut bssl_sys::RSA);
impl PublicKey {
/// Parse a DER-encoded RSAPublicKey structure (from RFC 8017).
pub fn from_der_rsa_public_key(der: &[u8]) -> Option<Self> {
Some(PublicKey(parse_with_cbs(
der,
// Safety: `ptr` is a non-null result from `RSA_parse_public_key` here.
|ptr| unsafe { bssl_sys::RSA_free(ptr) },
// Safety: cbs is valid per `parse_with_cbs`.
|cbs| unsafe { bssl_sys::RSA_parse_public_key(cbs) },
)?))
}
/// Serialize to a DER-encoded RSAPublicKey structure (from RFC 8017).
pub fn to_der_rsa_public_key(&self) -> Buffer {
cbb_to_buffer(/*initial_capacity=*/ 300, |cbb| unsafe {
// Safety: `self.0` is valid by construction.
assert_eq!(1, bssl_sys::RSA_marshal_public_key(cbb, self.0))
})
}
/// Parse a DER-encoded SubjectPublicKeyInfo. This format is found in,
/// for example, X.509 certificates.
pub fn from_der_subject_public_key_info(spki: &[u8]) -> Option<Self> {
// Safety: `EVP_pkey_rsa` is always safe to call.
let alg = unsafe { bssl_sys::EVP_pkey_rsa() };
let mut pkey =
scoped::EvpPkey::from_der_subject_public_key_info(spki, core::slice::from_ref(&alg))?;
let rsa = unsafe { bssl_sys::EVP_PKEY_get1_RSA(pkey.as_ffi_ptr()) };
if !rsa.is_null() {
// Safety: `EVP_PKEY_get1_RSA` adds a reference so we are not
// stealing ownership from `pkey`.
Some(PublicKey(rsa))
} else {
None
}
}
/// Serialize to a DER-encoded SubjectPublicKeyInfo. This format is found
/// in, for example, X.509 certificates.
pub fn to_der_subject_public_key_info(&self) -> Buffer {
let mut pkey = scoped::EvpPkey::new();
// Safety: this takes a reference to `self.0` and so doesn't steal ownership.
assert_eq!(1, unsafe {
bssl_sys::EVP_PKEY_set1_RSA(pkey.as_ffi_ptr(), self.0)
});
cbb_to_buffer(384, |cbb| unsafe {
// The arguments are valid so this will only fail if out of memory,
// which this crate doesn't handle.
assert_eq!(1, bssl_sys::EVP_marshal_public_key(cbb, pkey.as_ffi_ptr()));
})
}
/// Verify that `signature` is a valid signature of a digest of
/// `signed_msg`, by this public key. The digest of the message will be
/// computed with the specified hash function.
pub fn verify_pkcs1<Hash: digest::Algorithm>(
&self,
signed_msg: &[u8],
signature: &[u8],
) -> Result<(), InvalidSignatureError> {
let digest = Hash::hash_to_vec(signed_msg);
// Safety: `get_md` always returns a valid pointer.
let hash_nid = unsafe { bssl_sys::EVP_MD_nid(Hash::get_md(sealed::Sealed).as_ptr()) };
let result = unsafe {
// Safety: all buffers are valid and `self.0` is valid by construction.
bssl_sys::RSA_verify(
hash_nid,
digest.as_slice().as_ffi_ptr(),
digest.len(),
signature.as_ffi_ptr(),
signature.len(),
self.0,
)
};
if result == 1 {
Ok(())
} else {
Err(InvalidSignatureError)
}
}
}
// Safety:
//
// An `RSA` is safe to use from multiple threads so long as no mutating
// operations are performed. (Reference count changes don't count as mutating.)
// No mutating operations are performed. `RSA_verify` takes a non-const pointer
// but the BoringSSL docs specifically say that "these functions are considered
// non-mutating for thread-safety purposes and may be used concurrently."
unsafe impl Sync for PublicKey {}
unsafe impl Send for PublicKey {}
impl Drop for PublicKey {
fn drop(&mut self) {
// Safety: this object owns `self.0`.
unsafe { bssl_sys::RSA_free(self.0) }
}
}
#[cfg(feature = "std")]
impl std::fmt::Debug for PublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "RSA PublicKey")
}
}
/// The set of supported RSA key sizes for key generation.
#[allow(missing_docs)]
pub enum KeySize {
Rsa2048 = 2048,
Rsa3072 = 3072,
Rsa4096 = 4096,
}
/// An RSA private key.
pub struct PrivateKey(*mut bssl_sys::RSA);
impl PrivateKey {
/// Generate a fresh RSA private key of the given size.
pub fn generate(size: KeySize) -> Self {
let e = scoped::Bignum::from_u64(bssl_sys::RSA_F4 as u64);
let ptr = unsafe { bssl_sys::RSA_new() };
assert!(!ptr.is_null());
let result = unsafe {
// Safety: `rsa` and `e` are valid and initialized, just above.
bssl_sys::RSA_generate_key_ex(ptr, size as core::ffi::c_int, e.as_ffi_ptr(), null_mut())
};
assert_eq!(1, result);
// Safety: this function owns `ptr` and thus can move ownership here.
Self(ptr)
}
/// Parse a DER-encoded RSAPrivateKey structure (from RFC 8017).
pub fn from_der_rsa_private_key(der: &[u8]) -> Option<Self> {
Some(PrivateKey(parse_with_cbs(
der,
// Safety: `ptr` is a non-null result from `RSA_parse_private_key` here.
|ptr| unsafe { bssl_sys::RSA_free(ptr) },
// Safety: `cbs` is valid per `parse_with_cbs`.
|cbs| unsafe { bssl_sys::RSA_parse_private_key(cbs) },
)?))
}
/// Serialize to a DER-encoded RSAPrivateKey structure (from RFC 8017).
pub fn to_der_rsa_private_key(&self) -> Buffer {
cbb_to_buffer(/*initial_capacity=*/ 512, |cbb| unsafe {
// Safety: `self.0` is valid by construction.
assert_eq!(1, bssl_sys::RSA_marshal_private_key(cbb, self.0))
})
}
/// Parse a DER-encrypted PrivateKeyInfo struct (from RFC 5208). This is often called "PKCS#8 format".
pub fn from_der_private_key_info(der: &[u8]) -> Option<Self> {
// Safety: `EVP_pkey_rsa` is always safe to call.
let alg = unsafe { bssl_sys::EVP_pkey_rsa() };
let mut pkey =
scoped::EvpPkey::from_der_private_key_info(der, core::slice::from_ref(&alg))?;
// Safety: `pkey` is valid and was created just above.
let rsa = unsafe { bssl_sys::EVP_PKEY_get1_RSA(pkey.as_ffi_ptr()) };
// We only passed one allowed algorithm, an RSA algorithm.
assert!(!rsa.is_null());
Some(Self(rsa))
}
/// Serialize to a DER-encrypted PrivateKeyInfo struct (from RFC 5208). This is often called "PKCS#8 format".
pub fn to_der_private_key_info(&self) -> Buffer {
let mut pkey = scoped::EvpPkey::new();
assert_eq!(1, unsafe {
// Safety: `pkey` was just constructed. This takes a reference and
// so doesn't steal ownership from `self`.
bssl_sys::EVP_PKEY_set1_RSA(pkey.as_ffi_ptr(), self.0)
});
unsafe {
cbb_to_buffer(/*initial_capacity=*/ 384, |cbb| {
// Safety: `pkey` is valid and owned by this function.
assert_eq!(1, bssl_sys::EVP_marshal_private_key(cbb, pkey.as_ffi_ptr()));
})
}
}
/// Compute the signature of the digest of `to_be_signed` with PKCS#1 using
/// this private key. The specified hash function is used to compute the
// digest.
pub fn sign_pkcs1<Hash: digest::Algorithm>(&self, to_be_signed: &[u8]) -> Vec<u8> {
let digest = Hash::hash_to_vec(to_be_signed);
// Safety: `get_md` always returns a valid pointer.
let hash_nid = unsafe { bssl_sys::EVP_MD_nid(Hash::get_md(sealed::Sealed).as_ptr()) };
let max_output = unsafe { bssl_sys::RSA_size(self.0) } as usize;
unsafe {
with_output_vec(max_output, |out_buf| {
let mut out_len: core::ffi::c_uint = 0;
// Safety: `out_buf` points to at least `RSA_size` bytes, as
// required. `self.0` is valid by construction.
let result = bssl_sys::RSA_sign(
hash_nid,
digest.as_slice().as_ffi_ptr(),
digest.len(),
out_buf,
&mut out_len,
self.0,
);
// `RSA_sign` should always be successful unless it's out of
// memory, which this crate doesn't handle.
assert_eq!(1, result);
let out_len = out_len as usize;
assert!(out_len <= max_output);
// Safety: `out_len` bytes have been written.
out_len
})
}
}
/// Return the public key corresponding to this private key.
pub fn as_public(&self) -> PublicKey {
// Safety: `self.0` is valid by construction and `RSA_up_ref` means
// we we can pass an ownership reference to `PublicKey`.
unsafe { bssl_sys::RSA_up_ref(self.0) };
PublicKey(self.0)
}
}
// Safety:
//
// An `RSA` is safe to use from multiple threads so long as no mutating
// operations are performed. (Reference count changes don't count as mutating.)
// No mutating operations are performed. `RSA_sign` takes a non-const pointer
// but the BoringSSL docs specifically say that "these functions are considered
// non-mutating for thread-safety purposes and may be used concurrently."
unsafe impl Sync for PrivateKey {}
unsafe impl Send for PrivateKey {}
impl Drop for PrivateKey {
fn drop(&mut self) {
// Safety: `self.0` is always owned by this struct.
unsafe { bssl_sys::RSA_free(self.0) }
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn sign_and_verify() {
let key = PrivateKey::from_der_private_key_info(TEST_PKCS8_BYTES).unwrap();
let signed_msg = b"hello world";
let sig = key.sign_pkcs1::<digest::Sha256>(signed_msg);
assert!(key
.as_public()
.verify_pkcs1::<digest::Sha256>(signed_msg, &sig)
.is_ok());
}
#[test]
fn no_rsa_pss_spki() {
// `from_der_subject_public_key_info` should not accept id-RSASSA-PSS.
const RSA_PSS_SPKI: &[u8] = b"\x30\x82\x01\x56\x30\x41\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0a\x30\x34\xa0\x0f\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa1\x1c\x30\x1a\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x08\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa2\x03\x02\x01\x20\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xcd\x00\x81\xea\x7b\x2a\xe1\xea\x06\xd5\x9f\x7c\x73\xd9\xff\xb9\x4a\x09\x61\x5c\x2e\x4b\xa7\xc6\x36\xce\xf0\x8d\xd3\x53\x3e\xc3\x18\x55\x25\xb0\x15\xc7\x69\xb9\x9a\x77\xd6\x72\x5b\xf9\xc3\x53\x2a\x9b\x6e\x5f\x66\x27\xd5\xfb\x85\x16\x07\x68\xd3\xdd\xa9\xcb\xd3\x59\x74\x51\x17\x17\xdc\x3d\x30\x9d\x2f\xc4\x7e\xe4\x1f\x97\xe3\x2a\xdb\x7f\x9d\xd8\x64\xa1\xc4\x76\x7a\x66\x6e\xcd\x71\xbc\x1a\xac\xf5\xe7\x51\x7f\x4b\x38\x59\x4f\xea\x9b\x05\xe4\x2d\x5a\xda\x99\x12\x00\x80\x13\xe4\x53\x16\xa4\xd9\xbb\x8e\xd0\x86\xb8\x8d\x28\x75\x8b\xac\xaf\x92\x2d\x46\xa8\x68\xb4\x85\xd2\x39\xc9\xba\xeb\x0e\x2b\x64\x59\x27\x10\xf4\x2b\x2d\x1e\xa0\xa4\xb4\x80\x2c\x0b\xec\xab\x32\x8f\x8a\x68\xb0\x07\x3b\xdb\x54\x6f\xee\xa9\x80\x9d\x28\x49\x91\x2b\x39\x0c\x15\x32\xbc\x7e\x29\xc7\x65\x8f\x81\x75\xfa\xe4\x6f\x34\x33\x2f\xf8\x7b\xca\xb3\xe4\x06\x49\xb9\x85\x77\x86\x9d\xa0\xea\x71\x83\x53\xf0\x72\x27\x54\x88\x69\x13\x64\x87\x60\xd1\x22\xbe\x67\x6e\x0f\xc4\x83\xdd\x20\xff\xc3\x1b\xda\x96\xa3\x19\x66\xc9\xaa\x2e\x75\xad\x03\xde\x47\xe1\xc4\x4f\x02\x03\x01\x00\x01";
let key = PublicKey::from_der_subject_public_key_info(RSA_PSS_SPKI);
assert!(key.is_none());
}
#[test]
fn no_rsa_pss_pkcs8() {
// `from_der_private_key_info` should not accept id-RSASSA-PSS.
const RSA_PSS_PKCS8: &[u8] = b"\x30\x82\x04\xf0\x02\x01\x00\x30\x41\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0a\x30\x34\xa0\x0f\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa1\x1c\x30\x1a\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x08\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\xa2\x03\x02\x01\x20\x04\x82\x04\xa6\x30\x82\x04\xa2\x02\x01\x00\x02\x82\x01\x01\x00\xcd\x00\x81\xea\x7b\x2a\xe1\xea\x06\xd5\x9f\x7c\x73\xd9\xff\xb9\x4a\x09\x61\x5c\x2e\x4b\xa7\xc6\x36\xce\xf0\x8d\xd3\x53\x3e\xc3\x18\x55\x25\xb0\x15\xc7\x69\xb9\x9a\x77\xd6\x72\x5b\xf9\xc3\x53\x2a\x9b\x6e\x5f\x66\x27\xd5\xfb\x85\x16\x07\x68\xd3\xdd\xa9\xcb\xd3\x59\x74\x51\x17\x17\xdc\x3d\x30\x9d\x2f\xc4\x7e\xe4\x1f\x97\xe3\x2a\xdb\x7f\x9d\xd8\x64\xa1\xc4\x76\x7a\x66\x6e\xcd\x71\xbc\x1a\xac\xf5\xe7\x51\x7f\x4b\x38\x59\x4f\xea\x9b\x05\xe4\x2d\x5a\xda\x99\x12\x00\x80\x13\xe4\x53\x16\xa4\xd9\xbb\x8e\xd0\x86\xb8\x8d\x28\x75\x8b\xac\xaf\x92\x2d\x46\xa8\x68\xb4\x85\xd2\x39\xc9\xba\xeb\x0e\x2b\x64\x59\x27\x10\xf4\x2b\x2d\x1e\xa0\xa4\xb4\x80\x2c\x0b\xec\xab\x32\x8f\x8a\x68\xb0\x07\x3b\xdb\x54\x6f\xee\xa9\x80\x9d\x28\x49\x91\x2b\x39\x0c\x15\x32\xbc\x7e\x29\xc7\x65\x8f\x81\x75\xfa\xe4\x6f\x34\x33\x2f\xf8\x7b\xca\xb3\xe4\x06\x49\xb9\x85\x77\x86\x9d\xa0\xea\x71\x83\x53\xf0\x72\x27\x54\x88\x69\x13\x64\x87\x60\xd1\x22\xbe\x67\x6e\x0f\xc4\x83\xdd\x20\xff\xc3\x1b\xda\x96\xa3\x19\x66\xc9\xaa\x2e\x75\xad\x03\xde\x47\xe1\xc4\x4f\x02\x03\x01\x00\x01\x02\x82\x01\x00\x60\x29\x7a\xc7\x99\x1b\x16\x7a\x06\xd6\xb2\x47\x58\xb8\xcb\xe2\x08\xbe\xb9\xb2\xd9\xec\x97\x38\xbd\x80\xf9\x0a\x2e\x35\x00\x5d\xd7\xce\x29\x2d\x9e\x29\xba\x88\x5b\xd3\x16\xfe\xf1\xf2\x09\x13\xbc\x0a\xc9\x0d\x6b\x08\x08\xb2\x41\x4d\x82\x10\x44\x41\xd8\x62\x4a\x33\xce\x02\x33\xc8\xf7\x80\xa4\x8b\x37\x5a\xff\x02\xd7\x67\x12\x22\x8a\x70\x24\x84\xdb\x3f\x9e\xbe\xcc\xcf\xbb\xee\x17\x09\xdb\xa1\x82\x80\x0d\x94\x9e\x9e\x42\x16\xe0\xbf\xf3\x55\x83\x88\xf8\xbd\x90\xda\x37\x3a\x1d\x82\x74\x3e\xc3\xfb\xdd\x14\x27\xfd\x16\x82\x5a\x65\x7a\x31\x69\x12\xe8\x69\x53\x65\x11\x7c\xa2\xf8\x45\xc9\x09\x40\x5f\xca\xc5\x5f\x89\x5f\xc1\x5d\x20\x38\x6c\x26\xee\x78\xc9\xe9\x90\x75\x02\x9a\x17\x8a\x6c\x1e\x4c\xf0\xc2\x00\xe8\xa9\xcf\xb2\x7e\x9d\x15\x6f\x86\xe6\xc2\xad\xc2\x2b\x1a\x84\xa1\xcd\x5c\xa5\xb2\x79\x08\x75\xd7\x94\x07\xc8\x4b\x35\x23\x95\xcb\x81\xcc\x3f\xed\x5b\xb0\x43\xb6\x9e\xde\x0c\x07\x20\x45\x50\x02\x5c\xee\x8c\x5f\x44\x01\x70\xb6\x12\x0b\xb4\x8e\x0f\x74\x7b\xcd\x8f\x52\x21\x10\x85\x0d\xf0\x43\xc4\x28\xdf\xd1\x87\x05\x31\x02\x81\x81\x00\xf6\xf9\x61\xb4\x7c\xbc\x03\x5d\x3a\xed\xeb\xc7\xde\x85\x0a\x95\x6b\x65\xec\xdb\x9c\xf6\x07\x64\x06\x3f\x15\xaa\x48\x55\x3c\x58\xd9\x72\xfe\x66\x75\x05\x6e\x35\xdd\xfd\xc3\x7b\xf3\xb9\xf2\xf6\x22\xee\x27\x13\x37\x25\x68\x49\xc9\xbe\xf2\x17\x6f\xe8\xf7\xc3\xf8\xbb\x91\xba\x37\x4d\xd5\x3b\xaf\x3d\xec\x81\x4d\x2b\xde\xc1\x0c\x1f\xdc\x88\xcd\xd1\x68\x76\xf2\x6b\x1e\xdf\xa3\xf0\x94\x19\x7e\xdf\x4d\x42\xff\x1f\xb2\x97\x11\x03\xb8\x98\xca\x85\x9c\x42\x72\x87\x08\x6a\x84\x2a\xb4\x10\xbb\x69\xcf\x2d\x35\xaf\x6b\xe3\x02\x81\x81\x00\xd4\x7e\x72\x4a\x7f\xf4\x10\x48\xb2\x70\xc2\x52\x4a\x41\x01\x87\x8b\x73\x15\x9b\xb7\x3d\x3d\xbc\x18\x7b\x22\x0e\x63\x5b\x35\x34\xf9\x6e\x24\x3a\x18\x4d\x93\xf8\x60\xb6\xbf\xbb\x6b\x71\xc1\xed\x9a\x1e\x1f\x45\x85\x83\x02\x3c\x30\x1e\x96\xa6\x92\xc1\xa0\x8b\x53\xd0\xec\x9c\xa9\x10\x10\x0d\x80\x45\x1e\x3b\x7d\xc6\xa0\x1b\xac\x4a\xec\xef\x8d\xf7\x98\x84\x6b\xc2\x35\xa0\x8c\xbb\xa2\xcf\x4c\x06\x80\x4c\xc1\x12\x19\xe9\x56\x08\xc7\x14\xe3\xf1\x43\x0d\x49\x1f\xad\xbb\xa3\x2a\x57\x51\xa0\x4f\x97\x74\x58\x34\xc9\xa5\x02\x81\x80\x21\xf2\x45\x2b\xb9\xb9\x5d\xfd\x02\x8c\x91\x4b\xf7\x99\xf1\xca\x77\xe8\x9a\x95\xd5\x0d\x3c\x16\xd3\x84\xf8\x45\x5f\x8b\xd7\xaf\x9e\xb3\xdf\xa3\xd5\x91\xd9\x84\x2d\xef\x23\x5f\x76\x30\xa8\xe4\x8c\x08\x8f\xf6\x64\x2e\x10\x17\x94\x53\x5a\x93\x3e\x1e\x97\x6f\xa8\x50\x9f\xc7\x28\xb2\xda\x0c\x4a\x1a\x08\xd7\xfc\xf3\x7a\xba\xae\x1f\xf3\x00\x1a\xca\x1d\xc1\xbb\xb0\x5d\x9d\xff\xba\xa1\xa0\x9f\x7f\xb1\xee\xf3\x82\x37\xd9\xeb\xcc\xc7\x22\xb9\x33\x84\x36\xdd\xe7\x11\x91\x12\x79\x8c\x26\x80\x9c\x1a\x8d\xec\x43\x20\x61\x02\x81\x80\x1f\x75\x10\xaa\x62\xc2\xd8\xde\x4a\x3c\x53\x28\x27\x81\xf4\x1e\x02\xd0\xe8\xb4\x02\xae\x78\x43\x2e\x44\x9c\x48\x11\x01\x61\xa1\x14\x03\xf0\x2d\x01\x88\x0a\x8d\xcc\x93\x81\x52\xd7\x97\x21\xa4\x71\x1a\x60\x7a\xc4\x47\x1e\xbf\x96\x48\x10\xf9\x5b\xe4\x7a\x45\xe6\x04\x99\xe2\x9f\x4c\x97\x73\xc8\x37\x73\x40\x4f\x60\x66\x37\x72\x8c\x2d\x03\x51\xbb\x03\xc3\x26\xc8\xbb\x73\xa7\x21\xe7\xfa\x54\x40\xea\x21\x72\xbb\xa1\x46\x5f\xcc\x30\xdc\xb0\xd9\xf8\x99\x30\xe8\x15\xaa\x1f\x7f\x97\x29\xa8\x57\xe0\x0e\x03\x38\xdd\x59\x02\x81\x80\x4d\x1f\x0d\x75\x6f\xe7\x7e\x01\x09\x9a\x65\x2f\x50\xa8\x8b\x7b\x68\x5d\xc5\xbf\x00\x98\x1d\x5d\x23\x76\xfd\x0c\x6f\xe2\x9c\xd5\xb6\x38\x73\x44\x79\x30\x5a\x73\xad\x3c\x15\x99\xd3\x9e\xae\x3b\xae\x03\x5f\xbd\x6f\xed\x07\xc2\x8d\xe7\x05\x93\x38\x79\xa0\x6e\x48\xe6\xa6\x03\x68\x6e\xd8\xe2\x56\x0a\x5f\x6a\xf1\xf2\xc2\x4f\xaf\x4a\xa9\x60\xe3\x82\x18\x6f\x15\xee\xdc\xe9\xa2\x49\x1a\xe7\x30\x68\x0d\xd4\xcf\x77\x8b\x70\xfa\xa8\x68\x26\xab\x32\x23\x47\x7c\xc9\x13\x77\xb1\x9a\x6d\x5a\x2e\xae\xa2\x19\x76\x0b\xee\xd5";
let key = PrivateKey::from_der_private_key_info(RSA_PSS_PKCS8);
assert!(key.is_none());
}
}
// RSA generation is slow, but serialized keys are large. In order to use this
// in doctests, it's included here and public, but undocumented.
#[doc(hidden)]
pub const TEST_PKCS8_BYTES: &[u8] = b"\x30\x82\x04\xbd\x02\x01\x00\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x04\x82\x04\xa7\x30\x82\x04\xa3\x02\x01\x00\x02\x82\x01\x01\x00\x98\x3f\xf5\xc4\x89\xb7\x6f\x12\xc8\xb5\x82\xaa\x98\xe6\x75\x39\xc4\x44\x46\xa0\x45\x62\x42\x43\x21\x81\xa0\x53\x17\x47\xb3\xdc\xfc\x3b\x76\x03\xd6\xd4\xce\x5e\x9d\x22\xe5\xa3\x59\xa2\x47\x0c\xe4\x82\x33\x7a\x21\xa5\x61\x2a\x77\xa2\x6b\xfa\xa3\x45\x41\x50\xc2\xf7\x0d\xe1\xa6\x3a\x83\x5b\xe6\xb8\x1f\x24\x1e\x24\x89\xf8\x8d\xde\x5f\xf1\x50\x27\x0f\x2b\xbe\x58\xaa\x64\x67\xef\x22\x57\x1e\xf4\x3f\x2e\xba\x4b\x2f\xc3\x5e\x67\xcc\xc3\xf6\xdd\x6b\x31\x58\xb9\xbd\x7b\xf9\x23\xac\xf2\xa9\xb6\x8f\x88\x75\x0f\x73\xdf\xd2\x14\xaa\x41\x28\x5c\x9a\xd6\xc4\xab\x6f\xb0\x53\xb9\x0a\x2c\xfb\x56\x6e\x56\x94\xaa\x1a\x25\x29\x3b\x01\x0c\x7e\x44\x1b\xe1\x76\x12\x73\xc4\x16\x62\x64\x3d\xe6\xf7\x9f\x69\x3f\xc9\x3b\x75\xd6\x80\xee\x87\x68\x83\xde\x2d\x18\xe4\x26\xdd\x1a\x02\xd8\xd2\x1d\xb6\xf1\x71\xf5\x63\x62\x0c\xd7\x35\x21\xc6\x75\xb4\xd5\x0f\x89\x08\x17\x13\x24\x07\xc2\x7c\x73\xe2\x17\x00\x12\x8a\xc9\x39\xdb\xf0\xc8\x6f\x1f\xf7\x99\xed\x8c\x67\x9c\xf2\x30\x5c\xd0\xd0\x0d\xc1\x15\x07\xa3\x1d\xf5\xd4\x92\x82\xfd\x9c\x5a\x11\x69\x3b\x02\x03\x01\x00\x01\x02\x82\x01\x00\x44\xe1\x5a\xfd\x8a\x18\xd5\x45\xb8\x4c\x76\x4b\x5c\x55\x97\x5f\x85\x2e\x26\x8d\xc8\x16\x46\x48\x3c\xd6\x7a\x84\x5d\x19\xf1\x83\xdf\x11\xbf\xb8\xc8\xef\x0a\x56\xbf\xdc\xd3\xeb\xed\x57\x7f\xb1\x93\x88\x5c\x65\xba\xe7\x29\x68\x9f\x2b\x7a\x92\xb0\x5f\x5a\xc7\x81\x0d\x68\xd8\x57\xee\x4d\x13\xbc\xf4\x3c\x12\x89\x18\x9a\xdb\x3a\xc4\x0a\xc0\x10\x35\x3b\xa5\xdc\xbe\x1c\x88\xc4\x84\xea\x12\x64\x4c\xb8\x71\x19\x93\x7e\x8e\x73\x1d\x9f\x04\x61\xa1\x97\x27\x82\x2e\xb6\x4d\x6a\x4f\xfb\xa4\xe5\xa7\x54\x94\xb5\xf1\x41\xc8\xa4\x3d\xa1\xe6\x4a\xf0\xdb\xbb\xc2\x91\x26\x9a\x0f\xbf\xdd\x57\x1e\x83\x5c\x9a\x7b\x28\x53\x1d\x2d\x44\x91\x1f\x02\x81\x7b\x6f\xb5\xf7\x48\x7d\xa0\x12\x22\xdb\xbf\xd9\x04\x17\xe4\x97\xf2\xac\x32\xf8\x70\xfa\x75\xe3\x5a\xb0\xef\x1f\x2d\x24\xb9\x26\x83\x33\xe7\x3c\x3c\xfb\x0b\xd8\x70\x33\x76\xb1\x1c\x1d\x38\x06\x0a\xdb\xbd\xd2\x34\x5e\xe6\xb1\x6f\x5d\x8f\x18\xac\x94\xd2\x0d\xee\x39\x0b\xa3\xb4\xcf\xf1\xe1\x91\x30\xcb\xce\xa5\x2f\xa9\xcc\x4f\xee\xe4\xdd\xee\x8a\x77\x0e\xd1\xbd\xcc\xb0\x11\x55\x15\x5e\x99\xf1\x02\x81\x81\x00\xd1\x75\x33\xe4\x31\xc2\xfc\x09\x6c\xf6\x04\x97\xc7\xa3\xb1\x88\x36\x26\xd8\x4e\x86\x2d\xb8\x99\x68\x97\xd8\x0b\xc6\xc3\xe7\x58\x49\xc3\x41\xcd\xcd\x33\x09\xa0\x90\xb2\x77\xfa\xa3\xb6\x71\x09\x33\x43\x0a\x6a\xd8\xc3\x36\xaf\xa9\x11\x54\x64\x77\x82\xf4\xf1\xe0\x12\x5a\xb8\x9f\x5a\x04\xb3\x29\xd4\xc6\xba\x4c\xdc\x04\x97\xfb\xb6\x7e\x1b\x89\x09\x0c\x8a\xb8\x6c\x9f\x2b\x91\x0d\x34\x18\x39\xf3\x38\xf9\xe6\xed\x29\x48\x30\xe4\x3c\x09\x15\x33\xe0\xb8\x2f\xd8\xfa\xf2\x6d\x1f\xf1\xee\x02\xc2\xb4\xf9\xf4\x63\x4b\xa5\x02\x81\x81\x00\xba\x14\x89\xff\x65\xb5\xe6\x52\x45\x23\x37\x5e\x0c\x62\xde\xe9\x7f\xa9\x05\xee\x28\x0d\x91\xb1\x99\xd6\x8b\xf8\x58\x50\x8b\xb1\xee\x57\xbd\x2b\x7b\xf0\x25\x03\xeb\xbc\x87\x73\xc8\xbf\x57\x16\xda\x49\x7a\x79\x82\x25\x99\x46\x9c\xb3\xd2\xd5\xb0\xae\xec\xeb\xbc\xd2\x4b\xae\xd0\x0a\x54\xcd\xad\x44\x90\x74\x79\xa2\x34\x73\x8a\x3a\x6c\x0b\x13\x20\x5d\xa4\xcc\x7b\xb4\x64\xcf\x61\x6e\xdf\xc1\x8c\xd4\x84\x22\xf1\x19\x32\x6d\xf1\x6f\xe1\x1e\xa5\xf6\x20\x6c\xc6\xa8\x9c\x4d\x8d\x59\xdf\x90\x71\x67\x1a\x48\xa3\x4b\x5f\x02\x81\x81\x00\x97\x4d\x8f\x7f\x7e\x86\xb8\x23\x62\xe7\x50\x28\x07\xd9\x72\x4b\xcf\xba\x3d\xb4\x73\x6e\xa1\x93\x87\x9f\x70\x3c\x09\x87\xc8\x1c\xd9\xa3\xc7\x6c\x0f\x97\x97\x93\xba\x12\x81\x62\xb7\x51\xf9\xd3\x48\x89\x5c\x04\x14\xb2\xe7\x54\xfa\xce\xfe\xe4\x58\x04\x6c\x46\x30\xb3\x71\x7f\x3d\xf4\xfb\xc2\x24\x2c\x84\xa5\x5d\x11\xed\xeb\x8f\xb3\xa2\xe2\xe7\x19\x77\x4a\xd9\xaf\xf5\x46\xb6\x50\x10\x5a\x93\xb9\xe3\x65\x79\xef\xc5\x4b\x55\xad\xf8\xc4\x22\xe1\xc7\xa9\xa5\x3e\x9a\xff\xf5\xde\x06\x98\x04\xbc\x7b\x98\xb7\x75\xe6\xd5\x02\x81\x80\x0a\x7f\x38\x1d\xa9\x2e\x2e\xb4\xfb\x63\x76\x2f\x1f\x01\xc0\xd3\x69\x39\x2e\xb5\x75\x9a\xf6\x5a\x0f\x74\x93\xe6\xc9\x8c\x99\xa4\xca\xee\x36\x24\xaa\xd4\x2c\x32\x61\x6c\xfc\x33\x22\xe2\xf0\x55\xc0\xb0\x9e\x71\x16\x4f\x6a\xab\x1a\x11\xe6\xd5\xd9\x26\xb5\x04\xc3\x5d\x15\x99\xe1\xf0\x83\x42\x2b\x01\x10\x29\x11\xe7\x7d\x8f\xfa\xff\x3a\xb3\x11\x3c\x25\x2c\x33\xc0\xd2\xb7\x51\x1f\x8c\xf2\xa0\x67\x82\x61\x85\xdb\x15\xf1\xcb\x53\xf0\x5c\xc1\xae\xd9\x08\x91\x3a\x4f\xae\xa9\x8d\x4c\xc1\x98\xd3\x5c\xde\x95\xb4\x68\x7f\x02\x81\x80\x7d\x3e\x6b\x2c\x16\xe8\x17\x2c\x27\x9c\xc5\xc5\xfb\x30\x1a\xf7\x32\x53\x93\xfe\xc1\xa0\x5d\xac\x7d\x6f\xba\x1b\x56\x7e\x34\xf6\xa7\x91\x1f\x39\x84\x1c\x94\x58\x13\xe2\xb9\xec\xb6\x24\xfe\x76\x35\x1b\xcc\x4f\x8e\x0d\x88\x5b\x5a\x6f\xb6\xa2\x0b\xc3\xb6\x98\x2d\xca\xce\xce\x26\xb4\x36\x37\x42\xa4\xc0\xa9\x85\x57\x4b\x6b\xc2\xed\x14\x96\xe5\xbc\x2b\x83\x32\xe9\x83\x24\x7f\x85\x74\x09\x3c\xfa\x45\xfd\x21\xeb\xd8\xa3\x02\xd2\x70\x0a\x9a\x9d\x7d\xe4\x39\xc4\x59\xc8\x16\x6f\xce\xd5\x1d\xea\x91\x4d\x12\x78\xc3\x30";