1 use crate::{oids, AlgorithmIdentifier}; 2 use picky_asn1::wrapper::{IntegerAsn1, OctetStringAsn1Container}; 3 #[cfg(not(feature = "legacy"))] 4 use serde::Deserialize; 5 use serde::{de, ser, Serialize}; 6 use std::fmt; 7 8 /// [Public-Key Cryptography Standards (PKCS) #8](https://tools.ietf.org/html/rfc5208#section-5) 9 /// 10 /// # Section 5 11 /// 12 /// Private-key information shall have ASN.1 type PrivateKeyInfo: 13 /// 14 /// ```not_rust 15 /// PrivateKeyInfo ::= SEQUENCE { 16 /// version Version, 17 /// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 18 /// privateKey PrivateKey, 19 /// attributes [0] IMPLICIT Attributes OPTIONAL } 20 /// 21 /// Version ::= INTEGER 22 /// 23 /// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier 24 /// 25 /// PrivateKey ::= OCTET STRING 26 /// 27 /// Attributes ::= SET OF Attribute 28 /// ``` 29 /// 30 /// The fields of type PrivateKeyInfo have the following meanings: 31 /// 32 /// `version` is the syntax version number, for compatibility with 33 /// future revisions of this document. It shall be 0 for this version 34 /// of the document. 35 /// 36 /// `privateKeyAlgorithm` identifies the private-key algorithm. One 37 /// example of a private-key algorithm is PKCS #1's rsaEncryption. 38 /// 39 /// `privateKey` is an octet string whose contents are the value of the 40 /// private key. The interpretation of the contents is defined in the 41 /// registration of the private-key algorithm. For an RSA private 42 /// key, for example, the contents are a BER encoding of a value of 43 /// type RSAPrivateKey. 44 /// 45 /// `attributes` is a set of attributes. These are the extended 46 /// information that is encrypted along with the private-key 47 /// information. 48 #[derive(Serialize, Debug, Clone, PartialEq)] 49 pub struct PrivateKeyInfo { 50 pub version: u8, 51 pub private_key_algorithm: AlgorithmIdentifier, 52 pub private_key: PrivateKeyValue, 53 //pub attributes 54 } 55 56 impl PrivateKeyInfo { new_rsa_encryption( modulus: IntegerAsn1, public_exponent: IntegerAsn1, private_exponent: IntegerAsn1, primes: (IntegerAsn1, IntegerAsn1), exponents: (IntegerAsn1, IntegerAsn1), coefficient: IntegerAsn1, ) -> Self57 pub fn new_rsa_encryption( 58 modulus: IntegerAsn1, 59 public_exponent: IntegerAsn1, 60 private_exponent: IntegerAsn1, 61 primes: (IntegerAsn1, IntegerAsn1), 62 exponents: (IntegerAsn1, IntegerAsn1), 63 coefficient: IntegerAsn1, 64 ) -> Self { 65 let private_key = PrivateKeyValue::RSA( 66 RSAPrivateKey { 67 version: vec![0].into(), 68 modulus, 69 public_exponent, 70 private_exponent, 71 prime_1: primes.0, 72 prime_2: primes.1, 73 exponent_1: exponents.0, 74 exponent_2: exponents.1, 75 coefficient, 76 } 77 .into(), 78 ); 79 80 Self { 81 version: 0, 82 private_key_algorithm: AlgorithmIdentifier::new_rsa_encryption(), 83 private_key, 84 } 85 } 86 } 87 88 impl<'de> de::Deserialize<'de> for PrivateKeyInfo { deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error> where D: de::Deserializer<'de>,89 fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error> 90 where 91 D: de::Deserializer<'de>, 92 { 93 struct Visitor; 94 95 impl<'de> de::Visitor<'de> for Visitor { 96 type Value = PrivateKeyInfo; 97 98 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 99 formatter.write_str("a valid DER-encoded PrivateKeyInfo (pkcs8)") 100 } 101 102 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> 103 where 104 A: de::SeqAccess<'de>, 105 { 106 let version = seq_next_element!(seq, PrivateKeyInfo, "version"); 107 if version != 0 { 108 return Err(serde_invalid_value!( 109 PrivateKeyInfo, 110 "unsupported version (valid version number: 0)", 111 "a supported PrivateKeyInfo" 112 )); 113 } 114 115 let private_key_algorithm: AlgorithmIdentifier = 116 seq_next_element!(seq, PrivateKeyInfo, "private key algorithm"); 117 let private_key = if private_key_algorithm.is_a(oids::rsa_encryption()) { 118 PrivateKeyValue::RSA(seq_next_element!(seq, PrivateKeyInfo, "rsa oid")) 119 } else { 120 return Err(serde_invalid_value!( 121 PrivateKeyInfo, 122 "unsupported algorithm", 123 "a supported algorithm" 124 )); 125 }; 126 127 Ok(PrivateKeyInfo { 128 version, 129 private_key_algorithm, 130 private_key, 131 }) 132 } 133 } 134 135 deserializer.deserialize_seq(Visitor) 136 } 137 } 138 139 #[derive(Debug, PartialEq, Clone)] 140 pub enum PrivateKeyValue { 141 RSA(OctetStringAsn1Container<RSAPrivateKey>), 142 } 143 144 impl ser::Serialize for PrivateKeyValue { serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error> where S: ser::Serializer,145 fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error> 146 where 147 S: ser::Serializer, 148 { 149 match self { 150 PrivateKeyValue::RSA(rsa) => rsa.serialize(serializer), 151 } 152 } 153 } 154 155 /// [PKCS #1: RSA Cryptography Specifications Version 2.2](https://tools.ietf.org/html/rfc8017.html#appendix-A.1.2) 156 /// 157 /// # Section A.1.2 158 /// 159 /// An RSA private key should be represented with the ASN.1 type RSAPrivateKey: 160 /// 161 /// ```not_rust 162 /// RSAPrivateKey ::= SEQUENCE { 163 /// version Version, 164 /// modulus INTEGER, -- n 165 /// publicExponent INTEGER, -- e 166 /// privateExponent INTEGER, -- d 167 /// prime1 INTEGER, -- p 168 /// prime2 INTEGER, -- q 169 /// exponent1 INTEGER, -- d mod (p-1) 170 /// exponent2 INTEGER, -- d mod (q-1) 171 /// coefficient INTEGER, -- (inverse of q) mod p 172 /// otherPrimeInfos OtherPrimeInfos OPTIONAL 173 /// } 174 /// ``` 175 #[derive(Serialize, Debug, Clone, PartialEq)] 176 #[cfg_attr(not(feature = "legacy"), derive(Deserialize))] 177 pub struct RSAPrivateKey { 178 pub version: IntegerAsn1, 179 pub modulus: IntegerAsn1, 180 pub public_exponent: IntegerAsn1, 181 pub private_exponent: IntegerAsn1, 182 pub prime_1: IntegerAsn1, 183 pub prime_2: IntegerAsn1, 184 pub exponent_1: IntegerAsn1, 185 pub exponent_2: IntegerAsn1, 186 pub coefficient: IntegerAsn1, 187 } 188 189 #[cfg(feature = "legacy")] 190 impl<'de> de::Deserialize<'de> for RSAPrivateKey { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>,191 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 192 where 193 D: de::Deserializer<'de>, 194 { 195 struct Visitor; 196 197 impl<'de> de::Visitor<'de> for Visitor { 198 type Value = RSAPrivateKey; 199 200 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 201 formatter.write_str("struct RSAPrivateKey with 6 or 9 elements") 202 } 203 204 fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error> 205 where 206 V: de::SeqAccess<'de>, 207 { 208 let version: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(0, &self))?; 209 let modulus: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(1, &self))?; 210 let public_exponent: IntegerAsn1 = 211 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; 212 let private_exponent: IntegerAsn1 = 213 seq.next_element()?.ok_or_else(|| de::Error::invalid_length(3, &self))?; 214 let prime_1: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(4, &self))?; 215 let prime_2: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(5, &self))?; 216 217 let (exponent_1, exponent_2, coefficient) = if let Some(exponent_1) = seq.next_element()? { 218 let exponent_2 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(7, &self))?; 219 let coefficient = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(8, &self))?; 220 (exponent_1, exponent_2, coefficient) 221 } else { 222 use num_bigint_dig::{BigUint, ModInverse}; 223 224 // conversion to num_bigint_dig format BigUint 225 let private_exponent = BigUint::from_bytes_be(private_exponent.as_unsigned_bytes_be()); 226 let prime_1 = BigUint::from_bytes_be(prime_1.as_unsigned_bytes_be()); 227 let prime_2 = BigUint::from_bytes_be(prime_2.as_unsigned_bytes_be()); 228 229 let exponent_1 = &private_exponent % (&prime_1 - 1u8); 230 let exponent_2 = &private_exponent % (&prime_2 - 1u8); 231 232 let coefficient = prime_2 233 .mod_inverse(prime_1) 234 .ok_or_else(|| { 235 de::Error::invalid_value( 236 de::Unexpected::Other("[RSAPrivateKey] no modular inverse for prime 1"), 237 &"an invertible prime 1 value", 238 ) 239 })? 240 .to_biguint() 241 .ok_or_else(|| { 242 de::Error::invalid_value( 243 de::Unexpected::Other("[RSAPrivateKey] BigUint conversion failed"), 244 &"a valid prime 1 value", 245 ) 246 })?; 247 248 // conversion to IntegerAsn1 249 let exponent_1 = IntegerAsn1::from_bytes_be_unsigned(exponent_1.to_bytes_be()); 250 let exponent_2 = IntegerAsn1::from_bytes_be_unsigned(exponent_2.to_bytes_be()); 251 let coefficient = IntegerAsn1::from_bytes_be_unsigned(coefficient.to_bytes_be()); 252 253 (exponent_1, exponent_2, coefficient) 254 }; 255 256 Ok(RSAPrivateKey { 257 version, 258 modulus, 259 public_exponent, 260 private_exponent, 261 prime_1, 262 prime_2, 263 exponent_1, 264 exponent_2, 265 coefficient, 266 }) 267 } 268 } 269 270 deserializer.deserialize_seq(Visitor) 271 } 272 } 273 274 impl RSAPrivateKey { 275 #[deprecated(note = "field is now public")] modulus(&self) -> &IntegerAsn1276 pub fn modulus(&self) -> &IntegerAsn1 { 277 &self.modulus 278 } 279 280 #[deprecated(note = "field is now public")] public_exponent(&self) -> &IntegerAsn1281 pub fn public_exponent(&self) -> &IntegerAsn1 { 282 &self.public_exponent 283 } 284 285 #[deprecated(note = "field is now public")] private_exponent(&self) -> &IntegerAsn1286 pub fn private_exponent(&self) -> &IntegerAsn1 { 287 &self.private_exponent 288 } 289 290 #[deprecated(note = "field is now public")] prime_1(&self) -> &IntegerAsn1291 pub fn prime_1(&self) -> &IntegerAsn1 { 292 &self.prime_1 293 } 294 295 #[deprecated(note = "field is now public")] prime_2(&self) -> &IntegerAsn1296 pub fn prime_2(&self) -> &IntegerAsn1 { 297 &self.prime_2 298 } 299 300 #[deprecated(note = "field is now public")] primes(&self) -> (&IntegerAsn1, &IntegerAsn1)301 pub fn primes(&self) -> (&IntegerAsn1, &IntegerAsn1) { 302 (&self.prime_1, &self.prime_2) 303 } 304 305 #[deprecated(note = "field is now public")] exponent_1(&self) -> &IntegerAsn1306 pub fn exponent_1(&self) -> &IntegerAsn1 { 307 &self.exponent_1 308 } 309 310 #[deprecated(note = "field is now public")] exponent_2(&self) -> &IntegerAsn1311 pub fn exponent_2(&self) -> &IntegerAsn1 { 312 &self.exponent_2 313 } 314 315 #[deprecated(note = "field is now public")] exponents(&self) -> (&IntegerAsn1, &IntegerAsn1)316 pub fn exponents(&self) -> (&IntegerAsn1, &IntegerAsn1) { 317 (&self.exponent_1, &self.exponent_2) 318 } 319 320 #[deprecated(note = "field is now public")] coefficient(&self) -> &IntegerAsn1321 pub fn coefficient(&self) -> &IntegerAsn1 { 322 &self.coefficient 323 } 324 325 #[deprecated(note = "field is now public")] into_public_components(self) -> (IntegerAsn1, IntegerAsn1)326 pub fn into_public_components(self) -> (IntegerAsn1, IntegerAsn1) { 327 (self.modulus, self.public_exponent) 328 } 329 } 330 331 #[cfg(test)] 332 mod tests { 333 use super::*; 334 335 #[test] pkcs_8_private_key()336 fn pkcs_8_private_key() { 337 let encoded = base64::decode( 338 "MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAq7BFUpkGp3+LQmlQ\ 339 Yx2eqzDV+xeG8kx/sQFV18S5JhzGeIJNA72wSeukEPojtqUyX2J0CciPBh7eqclQ\ 340 2zpAswIDAQABAkAgisq4+zRdrzkwH1ITV1vpytnkO/NiHcnePQiOW0VUybPyHoGM\ 341 /jf75C5xET7ZQpBe5kx5VHsPZj0CBb3b+wSRAiEA2mPWCBytosIU/ODRfq6EiV04\ 342 lt6waE7I2uSPqIC20LcCIQDJQYIHQII+3YaPqyhGgqMexuuuGx+lDKD6/Fu/JwPb\ 343 5QIhAKthiYcYKlL9h8bjDsQhZDUACPasjzdsDEdq8inDyLOFAiEAmCr/tZwA3qeA\ 344 ZoBzI10DGPIuoKXBd3nk/eBxPkaxlEECIQCNymjsoI7GldtujVnr1qT+3yedLfHK\ 345 srDVjIT3LsvTqw==", 346 ) 347 .expect("invalid base64"); 348 349 let modulus = IntegerAsn1::from(encoded[35..100].to_vec()); 350 let public_exponent = IntegerAsn1::from(encoded[102..105].to_vec()); 351 let private_exponent = IntegerAsn1::from(encoded[107..171].to_vec()); 352 let prime_1 = IntegerAsn1::from(encoded[173..206].to_vec()); 353 let prime_2 = IntegerAsn1::from(encoded[208..241].to_vec()); 354 let exponent_1 = IntegerAsn1::from(encoded[243..276].to_vec()); 355 let exponent_2 = IntegerAsn1::from(encoded[278..311].to_vec()); 356 let coefficient = IntegerAsn1::from(encoded[313..346].to_vec()); 357 358 let private_key = PrivateKeyInfo::new_rsa_encryption( 359 modulus, 360 public_exponent, 361 private_exponent, 362 (prime_1, prime_2), 363 (exponent_1, exponent_2), 364 coefficient, 365 ); 366 check_serde!(private_key: PrivateKeyInfo in encoded); 367 } 368 369 #[test] 370 #[cfg(feature = "legacy")] old_broken_key_legacy_support()371 fn old_broken_key_legacy_support() { 372 // Version previous to picky-asn1-x509 6.0.0 could generate weird keys with negative values 373 // https://github.com/Devolutions/picky-rs/issues/53 374 // We want to support these for now. 375 376 let encoded = base64::decode( 377 "MIIDMAIBADANBgkqhkiG9w0BAQEFAASCAxowggMWAgEAAoIBAOB9jOJvCkMHOc98Q\ 378 GPFikxAvBKANkme5f/nNuNnEnbefoKDFkS6ElfqASAAkIHxUREnRvBTTa6b+qba/0\ 379 DhBuXsYGCl8VF0pUE4JGujv1HIi5aRCar0WmY66s7DJ4uR3Nk9Jy0WeRiH4yyzEIG\ 380 8+6QDu4d/U6slWTmE8eZtQEE7rz4FGpQU9OhrGM3xJOIIbLX/xU2SFt83Xs3JREEt\ 381 bfrXQpSxAHmtwvlBKpeZacrcobm6eQKsoI2MIg3LFvoHs0+40dadm14ngpgwx4qqk\ 382 bG34jvWH13OhHRweFGNkQpcg99rlzZYkCM13e9EcmirQ9XYHuB5pHS31eznolZKbx\ 383 cCAwEAAQKCAQCrPFlopxaGxk48jCR5dkbln0NWQWInigMazf06PHcDIPgTCXbE+cH\ 384 gOWieRo/z7mTN1s3vpztMA0KQX9/wVzVx0Ho7fpiyb21WcEKnsIHRGk4PjZZ4Rmdm\ 385 L27IRGg3uA1jz5fAdrHsGksY34Wp0MOJ+ibjViY2GAkVLOlvwMoQds6eNIGO88T5O\ 386 fcmvutjK43ObU1vgx2ptTaLNAVczEE5VHqcLx4GZPv6k71afOQfIDQerIpsGb4gvr\ 387 1JdwYKb4z02z2SaNIA3Vly0q5s4r8uU36eg9z65utu93M7zI7f8/MX2byZ2Jz4b3T\ 388 nH10FURmbPoNQH/O2T0TbtT4M1y0xAoGA72JW0IcFxze7j7PPaP6cQN1IXvFDZUFF\ 389 dZHqFI8+4VPcv3EKTs+iQflM7pqtRuEWtwonIn3f7CGOx317uKwpVsZvfnDhXCUPJ\ 390 Q3pns7KgaROGXyruFFQ9gl6XsXGK02Wop9nX0/iRK3ruwZ4uJwDioEYcvGw+ocqAc\ 391 yOdodNnpUCgYDwEo/sPJNaPOzc7fpaQr2PUUJ3ksL0ncGRO2h1JGYgDtWe5u1srSI\ 392 DlpM2NdYSZyT04ebOF2SqNUBwY3LB1tPOFnjYwCutp4c75OYhOor7TodZHlzt3GeQ\ 393 ntUw6XbHX0ohTgs4u2NXwOTq5yKeW4VYzuevN5ksF8GoW2noalpn+w==", 394 ) 395 .unwrap(); 396 397 picky_asn1_der::from_bytes::<PrivateKeyInfo>(&encoded).unwrap(); 398 } 399 } 400