//! Private key components use super::*; use offsets::*; use crate::password::{ Password, }; #[allow(unused_imports)] use std::{ borrow::{ Borrow, Cow, }, mem::{ size_of, }, marker::Unpin, io::{ self, Write, Read, }, convert::{ TryFrom, }, }; use openssl::{ bn::BigNumRef, rsa::{ Rsa, }, pkey::{ Public, Private, HasPrivate, PKey, }, symm::Cipher, }; #[cfg(feature="async")] use tokio::{ io::{ AsyncWrite, AsyncRead, }, prelude::*, }; /// Container for the private & public parts of an RSA key /// /// # Notes /// It is always assumed that the internal consistancy and state of the components binary representations is correct. /// Incorrect internal state can cause panics on all operations. #[derive(Clone, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature="serialise", derive(Serialize,Deserialize))] pub struct RsaPrivateKey { data: Vec, offset_starts: Starts, offset: PrivateOffsetGroup, } impl fmt::Display for RsaPrivateKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", base64::encode(&self.data[..])) } } impl RsaPrivateKey { /// Generate a new RSA private key pub fn generate() -> Result { Ok(Rsa::generate(RSA_KEY_BITS)?.into()) } /// Create a new private key from its components pub fn new( n: impl Borrow, e: impl Borrow, d: impl Borrow, p: impl Borrow, q: impl Borrow, dmp1: impl Borrow, dmq1: impl Borrow, iqmp: impl Borrow ) -> Self { fn vectorise(b: impl Borrow, data: &mut Vec) -> usize { let bytes = b.borrow().to_vec(); let len = bytes.len(); data.extend(bytes); len } let mut data = Vec::new(); let offset = PrivateOffsetGroup { n: vectorise(n, &mut data), e: vectorise(e, &mut data), d: vectorise(d, &mut data), p: vectorise(p, &mut data), q: vectorise(q, &mut data), dmp1: vectorise(dmp1, &mut data), dmq1: vectorise(dmq1, &mut data), iqmp: vectorise(iqmp, &mut data), }; Self { offset_starts: offset.starts(), offset, data, } } } impl RsaPrivateKey { /// Try to get the RSA private key from this instance pub fn get_rsa_priv(&self) -> Result, Error> { Ok(Rsa::from_private_components( number!(self -> n), number!(self -> e), number!(self -> d), number!(self -> p), number!(self -> q), number!(self -> dmp1), number!(self -> dmq1), number!(self -> iqmp) )?) } /// Try to get the RSA public key from this instance of private key pub fn get_rsa_pub(&self) -> Result, Error> { Ok(Rsa::from_public_components( number!(self -> n), number!(self -> e) )?) } /// Get the public parts of this private key pub fn get_public_parts(&self) -> RsaPublicKey { RsaPublicKey::new( self.num_n(), self.num_e() ) } /// Create a PEM string from this instance pub fn to_pem(&self, pw: Option<&Password>) -> Result { let rsa = self.get_rsa_priv()?; Ok(std::str::from_utf8(&match pw { Some(password) => { rsa.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), password.as_ref())? }, None => { rsa.private_key_to_pem()? }, })?.to_owned()) } /// Try to create an instance from PEM, requesting password if needed pub fn from_pem(pem: impl AsRef, pw: F) -> Result where F: FnOnce() -> Option { let pem = pem.as_ref().as_bytes(); Ok(Rsa::private_key_from_pem_callback(pem, |buf| { if let Some(pw) = pw() { Ok(bytes::copy_slice(buf, pw.as_ref())) } else { Ok(0) } })?.into()) } /// Validates the RSA key parameters for correctness pub fn check_key(&self) -> bool { self.get_rsa_priv() .map(|rsa| rsa.check_key().unwrap_or(false)) .unwrap_or(false) } /// Try to construct an instance from bytes pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result { const OFF_SIZE: usize = size_of::(); let bytes = bytes.as_ref(); if bytes.len() < OFF_SIZE { return Err(Error::Binary(BinaryErrorKind::Length{expected: Some(OFF_SIZE), got: Some(bytes.len())})); } let offset = unsafe{ bytes::derefer_unchecked::(&bytes[..OFF_SIZE]) .read_unaligned() }; let bytes = &bytes[OFF_SIZE..]; let sz = offset.body_len(); if bytes.len() < sz { return Err(Error::Binary(BinaryErrorKind::Length{expected: Some(sz), got: Some(bytes.len())})); } Ok(Self{ data: Vec::from(&bytes[..]), offset_starts: offset.starts(), offset, }) } /// Write the binary representation of this instance to a new `Vec` pub fn to_bytes(&self) -> Vec { let mut output = Vec::new(); self.write_to_sync(&mut output).unwrap(); output } /// Return the length of the data body only (not including header). #[inline] pub fn len(&self) -> usize { self.data.len() } /// Write this private key as bytes to a stream #[cfg(feature="async")] pub async fn write_to(&self, to: &mut T) -> io::Result where T: AsyncWrite + Unpin + ?Sized { to.write_all(bytes::refer(&self.offset)).await?; to.write_all(&self.data[..]).await?; Ok(size_of::() + self.data.len()) } /// Write this private key as bytes to a stream pub fn write_to_sync(&self, to: &mut T) -> io::Result where T: Write + ?Sized { to.write_all(bytes::refer(&self.offset))?; to.write_all(&self.data[..])?; Ok(size_of::() + self.data.len()) } /// Read a private key from a stream #[cfg(feature="async")] pub async fn read_from(&self, from: &mut T) -> io::Result where T: AsyncRead + Unpin + ?Sized { const OFF_SIZE: usize = size_of::(); let offset: PrivateOffsetGroup = { union BufHack { buffer: [u8; OFF_SIZE], res: PrivateOffsetGroup, } let mut offsets = BufHack{buffer: [0u8; OFF_SIZE]}; unsafe { let buffer = &mut offsets.buffer; if buffer.len() != from.read_exact(&mut buffer[..]).await? { return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "couldn't read offsets")); } } unsafe{ offsets.res } }; let mut data = vec![0u8; offset.body_len()]; if from.read_exact(&mut data[..]).await? != data.len() { return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "couldn't read data body")); } Ok(Self { data, offset_starts: offset.starts(), offset }) } /// Read a private key from a stream pub fn read_from_sync(&self, from: &mut T) -> io::Result where T: Read + ?Sized { const OFF_SIZE: usize = size_of::(); let offset: PrivateOffsetGroup = { union BufHack { buffer: [u8; OFF_SIZE], res: PrivateOffsetGroup, } let mut offsets = BufHack{buffer: [0u8; OFF_SIZE]}; unsafe { let buffer = &mut offsets.buffer; from.read_exact(&mut buffer[..])?; } unsafe { offsets.res } }; let mut data = vec![0u8; offset.body_len()]; from.read_exact(&mut data[..])?; Ok(Self { data, offset_starts: offset.starts(), offset }) } } impl HasComponents for RsaPrivateKey { fn raw(&self) -> &[u8] { return &self.data[..] } } impl HasPublicComponents for RsaPrivateKey { fn n(&self) -> &[u8] { component!(self -> n) } fn e(&self) -> &[u8] { component!(self -> e) } } impl HasPrivateComponents for RsaPrivateKey { fn d(&self) -> &[u8] { component!(self -> d) } fn p(&self) -> &[u8] { component!(self -> p) } fn q(&self) -> &[u8] { component!(self -> q) } fn dmp1(&self) -> &[u8] { component!(self -> dmp1) } fn dmq1(&self) -> &[u8] { component!(self -> dmq1) } fn iqmp(&self) -> &[u8] { component!(self -> iqmp) } } impl From> for RsaPrivateKey where T: HasPrivate { fn from(key: Rsa) -> Self { Self::new( key.n(), key.e(), key.d(), key.p().unwrap(), key.q().unwrap(), key.dmp1().unwrap(), key.dmq1().unwrap(), key.iqmp().unwrap() ) } } impl From for Rsa { fn from(from: RsaPrivateKey) -> Self { from.get_rsa_priv().unwrap() } } impl From for RsaPublicKey { fn from(from: RsaPrivateKey) -> Self { from.get_public_parts() } } impl PublicKey for RsaPrivateKey { type KeyType = Private; type Error = Error; fn get_pkey_pub(&self) -> Result>, Self::Error> { Ok(Cow::Owned(PKey::from_rsa(self.get_rsa_priv()?)?)) } fn get_rsa_pub(&self) -> Result>>, Self::Error> { Ok(Some(Cow::Owned(self.get_pkey_pub()?.rsa()?))) } } impl PrivateKey for RsaPrivateKey{} impl From for Vec { #[inline] fn from(from: RsaPrivateKey) -> Self { from.to_bytes() } } impl TryFrom> for RsaPrivateKey { type Error = Error; #[inline] fn try_from(from: Vec) -> Result { Self::from_bytes(from) } }