use num_bigint_dig::{traits::ModInverse, BigUint}; use num_traits::identities::One; use rsa::{PublicKey, RSAPrivateKey}; use super::*; impl KeyExt for RSAPrivateKey { fn to_pem_pkcs8(&self) -> Result { let bytes = write_pkcs1(self).ok_or(KeyError::Serialize)?; let oid = yasna::models::ObjectIdentifier::from_slice(&RSA_OID); let contents = yasna::construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_i64(0); // version is 0 writer.next().write_sequence(|writer| { writer.next().write_oid(&oid); }); writer.next().write_bytes(&bytes); }); }); let p = pem::Pem { tag: "PRIVATE KEY".to_owned(), contents, }; Ok(pem::encode(&p)) } fn from_pem_pkcs8(pem: &str) -> Result { let data = pem::parse(pem).map_err(|_| KeyError::Pem)?; if data.tag != "PRIVATE KEY" { return Err(KeyError::Kind.into()); } let expected_oid = yasna::models::ObjectIdentifier::from_slice(&RSA_OID); let pkey = yasna::parse_der(&data.contents, |reader| { // Read the outer DER-encoded value reader.read_sequence(|reader| { let version = reader.next().read_i64()?; // PKCS#8 defines version == 0 if version != 0 { return Err(yasna::ASN1Error::new(yasna::ASN1ErrorKind::Invalid)); } let oid = reader .next() .read_sequence(|reader| reader.next().read_oid())?; // RSA defines OID == 1.2.840.113549.1.1.1 if oid != expected_oid { return Err(yasna::ASN1Error::new(yasna::ASN1ErrorKind::Invalid)); } let bytes = reader.next().read_bytes()?; parse_pkcs1(&bytes) }) })?; pkey.validate().map_err(|_| KeyError::Validate)?; Ok(pkey) } fn to_pem_pkcs1(&self) -> Result { let contents = write_pkcs1(self).ok_or(KeyError::Serialize)?; let p = pem::Pem { tag: "RSA PRIVATE KEY".to_owned(), contents, }; Ok(pem::encode(&p)) } fn from_pem_pkcs1(pem: &str) -> Result { let data = pem::parse(pem).map_err(|_| KeyError::Pem)?; if data.tag != "RSA PRIVATE KEY" { return Err(KeyError::Kind.into()); } let pkey = parse_pkcs1(&data.contents)?; pkey.validate().map_err(|_| KeyError::Validate)?; Ok(pkey) } } fn write_pkcs1(rsa: &RSAPrivateKey) -> Option> { let exp1 = rsa.d() % (rsa.primes()[0].clone() - BigUint::one()); let exp2 = rsa.d() % (rsa.primes()[1].clone() - BigUint::one()); let coeff = rsa.primes()[0] .clone() .mod_inverse(rsa.primes()[1].clone())?; Some(yasna::construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_i64(0); writer.next().write_biguint(&from_dig(rsa.n())); writer.next().write_biguint(&from_dig(rsa.e())); writer.next().write_biguint(&from_dig(rsa.d())); writer.next().write_biguint(&from_dig(&rsa.primes()[0])); writer.next().write_biguint(&from_dig(&rsa.primes()[1])); writer.next().write_biguint(&from_dig(&exp1)); writer.next().write_biguint(&from_dig(&exp2)); writer.next().write_bigint(&int_from_dig(&coeff)); }) })) } fn parse_pkcs1(bytes: &[u8]) -> Result { yasna::parse_der(bytes, |reader| { reader.read_sequence(|reader| { let version = reader.next().read_i64()?; // version 0 (two primes) is the only supported RSAPrivateKey version, 1 (multi-prime) is unsupported if version != 0 { return Err(yasna::ASN1Error::new(yasna::ASN1ErrorKind::Invalid)); } let modulus = reader.next().read_biguint()?; let pubexp = reader.next().read_biguint()?; let privexp = reader.next().read_biguint()?; let prime1 = reader.next().read_biguint()?; let prime2 = reader.next().read_biguint()?; // These need to be read or else the parser will error let _exp1 = reader.next().read_biguint()?; let _exp2 = reader.next().read_biguint()?; let _coeff = reader.next().read_biguint()?; let pkey = RSAPrivateKey::from_components( to_dig(&modulus), to_dig(&pubexp), to_dig(&privexp), vec![to_dig(&prime1), to_dig(&prime2)], ); Ok(pkey) }) }) }