1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use super::*;
use num_bigint_dig::{traits::ModInverse, BigUint};
use num_traits::identities::One;
use rsa::{PublicKeyParts, RSAPrivateKey};
use std::convert::TryInto;
impl KeyExt for RSAPrivateKey {
fn to_pem_pkcs8(&self) -> Result<String, KeyError> {
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);
writer.next().write_sequence(|writer| {
writer.next().write_oid(&oid);
writer.next().write_null();
});
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<Self, KeyError> {
let data = pem::parse(pem).map_err(|_| KeyError::Pem)?;
if data.tag != "PRIVATE KEY" {
return Err(KeyError::Kind);
}
data.try_into().map_err(KeyError::Parse)
}
fn to_pem_pkcs1(&self) -> Result<String, KeyError> {
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<Self, KeyError> {
let data = pem::parse(pem).map_err(|_| KeyError::Pem)?;
if data.tag != "RSA PRIVATE KEY" {
return Err(KeyError::Kind);
}
data.try_into().map_err(KeyError::Parse)
}
}
fn write_pkcs1(rsa: &RSAPrivateKey) -> Option<Vec<u8>> {
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));
})
}))
}