Make it work with Real PEM PKCS8 Keys

This commit is contained in:
asonix 2020-04-21 17:30:57 -05:00
parent 8dc04bd060
commit 444d9d730c
4 changed files with 59 additions and 3 deletions

View File

@ -1,6 +1,9 @@
# RSA PEM
_Converting between the PEM format and a RustCrypto RSA type_
This library will be useless after the next release of the RSA crate, which should have this
functionality baked in.
```rust
use rsa_pem::KeyExt as _;
use rsa::{RSAPrivateKey};

20
examples/read.rs Normal file
View File

@ -0,0 +1,20 @@
use rsa::RSAPrivateKey;
use rsa_pem::*;
fn main() {
let mut args = std::env::args();
let _ = args.next().unwrap();
let path = args.next().expect("File must be provided");
let pkcs8 = args.next().is_some();
let bytes = std::fs::read(path).unwrap();
let s = String::from_utf8(bytes).unwrap();
if pkcs8 {
RSAPrivateKey::from_pem_pkcs8(&s).unwrap();
} else {
RSAPrivateKey::from_pem_pkcs1(&s).unwrap();
}
println!("Read key!");
}

View File

@ -1,3 +1,19 @@
//! Read and Write PEM files from RSA types
//!
//! This library will be useless after the next release of the RSA crate, which should have this
//! functionality baked in.
//!
//! ### Examples
//! ```rust
//! use rsa_pem::KeyExt;
//! use rsa::RSAPrivateKey;
//! #
//! # let mut rng = rand::thread_rng();
//! # let private_key = RSAPrivateKey::new(&mut rng, 2048).unwrap();
//!
//! let pkcs8_string = private_key.to_pem_pkcs8().unwrap();
//! let private_key = RSAPrivateKey::from_pem_pkcs8(&pkcs8_string).unwrap();
//! ```
use num_bigint_dig::{BigInt, BigUint, Sign};
use thiserror::Error;
@ -6,31 +22,45 @@ mod public;
const RSA_OID: [u64; 7] = [1, 2, 840, 113549, 1, 1, 1];
/// Extensions to keys for formatting and reading PKCS1 and PKCS8 PEM strings
pub trait KeyExt {
/// Write a PKCS8 pem string
fn to_pem_pkcs8(&self) -> Result<String, KeyError>;
/// Read a PKCS8 pem string
fn from_pem_pkcs8(pem: &str) -> Result<Self, KeyError>
where
Self: Sized;
/// Write a PKCS1 pem string
fn to_pem_pkcs1(&self) -> Result<String, KeyError>;
/// Read a PKCS1 pem string
fn from_pem_pkcs1(pem: &str) -> Result<Self, KeyError>
where
Self: Sized;
}
/// Errors produced when serializing or deserializing keys
#[derive(Clone, Debug, Error)]
pub enum KeyError {
/// The PEM wrapper has the wrong name
#[error("Invalid key kind supplied")]
Kind,
/// The file isn't PEM encoded
#[error("Key not PEM-formatted")]
Pem,
/// Parsing the DER bytes failed
#[error("Error parsing key, {}", .0)]
Parse(#[from] yasna::ASN1Error),
/// The private key's fields don't make sense
#[error("Constructed key is invalid")]
Validate,
/// Failed to serialize to DER bytes
#[error("Could not serialize key")]
Serialize,
}

View File

@ -46,6 +46,7 @@ impl KeyExt for RSAPrivateKey {
writer.next().write_i64(0); // version is 0
writer.next().write_sequence(|writer| {
writer.next().write_oid(&oid);
writer.next().write_null();
});
writer.next().write_bytes(&bytes);
});
@ -82,9 +83,11 @@ impl KeyExt for RSAPrivateKey {
// Read AlgorithmIdentifier ::= AlgorithmIdentifier
debug!("Parsing oid");
let oid = reader
.next()
.read_sequence(|reader| reader.next().read_oid())?;
let oid = reader.next().read_sequence(|reader| {
let oid = reader.next().read_oid()?;
reader.next().read_null()?;
Ok(oid)
})?;
// RSA defines OID == 1.2.840.113549.1.1.1
if oid != expected_oid {