1use crate::p256::{PRIVATE_KEY_SIZE, PUBLIC_KEY_UNCOMPRESSED_SIZE, PrivateKey};
2
3const PKCS8_DER_LEN: usize = 138;
4
5const EC_PUBLIC_KEY_OID: &[u8] = &[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01];
6const SECP256R1_OID: &[u8] = &[0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07];
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Pkcs8Error {
10 InvalidLength,
11 InvalidSequence,
12 InvalidVersion,
13 InvalidAlgorithmIdentifier,
14 InvalidOctetString,
15 InvalidEcPrivateKey,
16 InvalidEcVersion,
17 InvalidPrivateKeyOctet,
18 InvalidPublicKeyExplicit,
19 InvalidPublicKeyBitString,
20 InvalidPublicKeyPrefix,
21 KeyDerivationFailed,
22}
23
24#[cfg(feature = "alloc")]
25impl core::fmt::Display for Pkcs8Error {
26 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27 match self {
28 Pkcs8Error::InvalidLength => write!(f, "invalid DER length"),
29 Pkcs8Error::InvalidSequence => write!(f, "invalid outer SEQUENCE"),
30 Pkcs8Error::InvalidVersion => write!(f, "invalid version"),
31 Pkcs8Error::InvalidAlgorithmIdentifier => write!(f, "invalid AlgorithmIdentifier"),
32 Pkcs8Error::InvalidOctetString => write!(f, "invalid OCTET STRING wrapping"),
33 Pkcs8Error::InvalidEcPrivateKey => write!(f, "invalid ECPrivateKey SEQUENCE"),
34 Pkcs8Error::InvalidEcVersion => write!(f, "invalid EC version"),
35 Pkcs8Error::InvalidPrivateKeyOctet => write!(f, "invalid private key OCTET STRING"),
36 Pkcs8Error::InvalidPublicKeyExplicit => write!(f, "invalid public key [1] EXPLICIT"),
37 Pkcs8Error::InvalidPublicKeyBitString => write!(f, "invalid public key BIT STRING"),
38 Pkcs8Error::InvalidPublicKeyPrefix => write!(f, "invalid public key prefix"),
39 Pkcs8Error::KeyDerivationFailed => write!(f, "key derivation failed"),
40 }
41 }
42}
43
44fn validate_fixed_prefix(der: &[u8]) -> Result<(), Pkcs8Error> {
45 if der.len() != PKCS8_DER_LEN {
46 return Err(Pkcs8Error::InvalidLength);
47 }
48
49 if der[0] != 0x30 || der[1] != 0x81 || der[2] != 0x87 {
51 return Err(Pkcs8Error::InvalidSequence);
52 }
53 if der[3] != 0x02 || der[4] != 0x01 || der[5] != 0x00 {
55 return Err(Pkcs8Error::InvalidVersion);
56 }
57 if der[6] != 0x30 || der[7] != 0x13 {
59 return Err(Pkcs8Error::InvalidAlgorithmIdentifier);
60 }
61 if der[8] != 0x06 || der[9] != 0x07 || der[10..17] != *EC_PUBLIC_KEY_OID {
63 return Err(Pkcs8Error::InvalidAlgorithmIdentifier);
64 }
65 if der[17] != 0x06 || der[18] != 0x08 || der[19..27] != *SECP256R1_OID {
67 return Err(Pkcs8Error::InvalidAlgorithmIdentifier);
68 }
69 if der[27] != 0x04 || der[28] != 0x6d {
71 return Err(Pkcs8Error::InvalidOctetString);
72 }
73 if der[29] != 0x30 || der[30] != 0x6b {
75 return Err(Pkcs8Error::InvalidEcPrivateKey);
76 }
77 if der[31] != 0x02 || der[32] != 0x01 || der[33] != 0x01 {
79 return Err(Pkcs8Error::InvalidEcVersion);
80 }
81 if der[34] != 0x04 || der[35] != 0x20 {
83 return Err(Pkcs8Error::InvalidPrivateKeyOctet);
84 }
85 if der[68] != 0xa1 || der[69] != 0x44 {
87 return Err(Pkcs8Error::InvalidPublicKeyExplicit);
88 }
89 if der[70] != 0x03 || der[71] != 0x42 || der[72] != 0x00 {
91 return Err(Pkcs8Error::InvalidPublicKeyBitString);
92 }
93 if der[73] != 0x04 {
95 return Err(Pkcs8Error::InvalidPublicKeyPrefix);
96 }
97
98 Ok(())
99}
100
101static TEMPLATE: [u8; PKCS8_DER_LEN] = [
102 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
108 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0xa1, 0x44, 0x03, 0x42, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122];
123
124const PRIVATE_KEY_OFFSET: usize = 36;
125const PUBLIC_KEY_OFFSET: usize = 73;
126
127pub fn encode_p256_pkcs8_der(key: &PrivateKey) -> Result<[u8; PKCS8_DER_LEN], Pkcs8Error> {
128 let public_key = key.public_key();
129 let pub_bytes = public_key.to_bytes();
130 let priv_bytes = key.to_bytes();
131
132 let mut der = TEMPLATE;
133 der[PUBLIC_KEY_OFFSET..PUBLIC_KEY_OFFSET + PUBLIC_KEY_UNCOMPRESSED_SIZE].copy_from_slice(&pub_bytes);
134 der[PRIVATE_KEY_OFFSET..PRIVATE_KEY_OFFSET + PRIVATE_KEY_SIZE].copy_from_slice(&priv_bytes);
135
136 Ok(der)
137}
138
139pub fn decode_p256_pkcs8_der(der: &[u8]) -> Result<PrivateKey, Pkcs8Error> {
140 validate_fixed_prefix(der)?;
141
142 let mut private_key = [0u8; PRIVATE_KEY_SIZE];
143 private_key.copy_from_slice(&der[PRIVATE_KEY_OFFSET..PRIVATE_KEY_OFFSET + PRIVATE_KEY_SIZE]);
144
145 let mut public_key = [0u8; PUBLIC_KEY_UNCOMPRESSED_SIZE];
146 public_key.copy_from_slice(&der[PUBLIC_KEY_OFFSET..PUBLIC_KEY_OFFSET + PUBLIC_KEY_UNCOMPRESSED_SIZE]);
147
148 PrivateKey::from_bytes(&private_key).map_err(|_| Pkcs8Error::KeyDerivationFailed)
149}
150
151#[cfg(test)]
152mod tests {
153 use super::*;
154
155 const TEST_PRIVATE_KEY: [u8; 32] = [
159 0x25, 0x55, 0x82, 0xfd, 0x0c, 0xce, 0x4c, 0x24, 0xb9, 0xbe, 0xdb, 0x09, 0xa7, 0x62, 0x06, 0xf9, 0x40, 0xdc,
160 0xf1, 0xc7, 0x43, 0x7d, 0xea, 0x0a, 0xb7, 0x14, 0x99, 0xc5, 0xac, 0xe7, 0x33, 0xe9,
161 ];
162
163 const TEST_PUBLIC_KEY: [u8; 65] = [
164 0x04, 0x1e, 0x9c, 0x23, 0xe8, 0x1a, 0x03, 0xc5, 0x4d, 0xd3, 0xc9, 0xed, 0x52, 0xcb, 0x2a, 0xde, 0x7a, 0x47,
165 0x13, 0xe5, 0x61, 0x3d, 0x70, 0x35, 0x79, 0xc7, 0x73, 0x9e, 0x0f, 0x13, 0x20, 0x60, 0xdc, 0xbc, 0x4a, 0x68,
166 0x7d, 0x3e, 0xb0, 0x99, 0x17, 0xd2, 0x62, 0xfc, 0x2f, 0x23, 0xc4, 0x76, 0xc7, 0xcb, 0xfc, 0xec, 0xf8, 0x4f,
167 0x11, 0xe4, 0x58, 0xb2, 0x46, 0xad, 0x75, 0x6d, 0x36, 0x17, 0xc7,
168 ];
169
170 fn decode_hex(hex_str: &str) -> Vec<u8> {
171 (0..hex_str.len())
172 .step_by(2)
173 .map(|i| u8::from_str_radix(&hex_str[i..i + 2], 16).unwrap())
174 .collect()
175 }
176
177 const TEST_DER_HEX: &str = "308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420255582fd0cce4c24b9bedb09a76206f940dcf1c7437dea0ab71499c5ace733e9a144034200041e9c23e81a03c54dd3c9ed52cb2ade7a4713e5613d703579c7739e0f132060dcbc4a687d3eb09917d262fc2f23c476c7cbfcecf84f11e458b246ad756d3617c7";
178
179 #[test]
180 fn encode_round_trip() {
181 let key = PrivateKey::from_bytes(&TEST_PRIVATE_KEY).unwrap();
182 let der = encode_p256_pkcs8_der(&key).unwrap();
183 let decoded = decode_p256_pkcs8_der(&der).unwrap();
184 assert_eq!(decoded.to_bytes(), TEST_PRIVATE_KEY);
185 assert_eq!(decoded.public_key().to_bytes(), TEST_PUBLIC_KEY);
186 }
187
188 #[test]
189 fn decode_known_vector() {
190 let der_bytes = decode_hex(TEST_DER_HEX);
191 let key = decode_p256_pkcs8_der(&der_bytes).unwrap();
192 assert_eq!(key.to_bytes(), TEST_PRIVATE_KEY);
193 assert_eq!(key.public_key().to_bytes(), TEST_PUBLIC_KEY);
194 }
195
196 #[test]
197 fn encode_matches_known_der() {
198 let key = PrivateKey::from_bytes(&TEST_PRIVATE_KEY).unwrap();
199 let der = encode_p256_pkcs8_der(&key).unwrap();
200 let expected = decode_hex(TEST_DER_HEX);
201 assert_eq!(der.as_slice(), expected.as_slice());
202 }
203
204 #[test]
205 fn decode_too_short() {
206 assert_eq!(decode_p256_pkcs8_der(&[0u8; 100]), Err(Pkcs8Error::InvalidLength));
207 }
208
209 #[test]
210 fn decode_too_long() {
211 assert_eq!(decode_p256_pkcs8_der(&[0u8; 200]), Err(Pkcs8Error::InvalidLength));
212 }
213
214 #[test]
215 fn decode_bad_sequence() {
216 let mut der = decode_hex(TEST_DER_HEX);
217 der[0] = 0x31;
218 assert_eq!(decode_p256_pkcs8_der(&der), Err(Pkcs8Error::InvalidSequence));
219 }
220
221 #[test]
222 fn decode_bad_version() {
223 let mut der = decode_hex(TEST_DER_HEX);
224 der[5] = 0x01;
225 assert_eq!(decode_p256_pkcs8_der(&der), Err(Pkcs8Error::InvalidVersion));
226 }
227
228 #[test]
229 fn decode_bad_algo_identifier() {
230 let mut der = decode_hex(TEST_DER_HEX);
231 der[10] = 0x00;
232 assert_eq!(decode_p256_pkcs8_der(&der), Err(Pkcs8Error::InvalidAlgorithmIdentifier));
233 }
234
235 #[test]
236 fn decode_bad_ec_version() {
237 let mut der = decode_hex(TEST_DER_HEX);
238 der[33] = 0x02;
239 assert_eq!(decode_p256_pkcs8_der(&der), Err(Pkcs8Error::InvalidEcVersion));
240 }
241
242 #[test]
243 fn decode_missing_public_key() {
244 let mut der = decode_hex(TEST_DER_HEX);
245 der[68] = 0x00;
246 assert_eq!(decode_p256_pkcs8_der(&der), Err(Pkcs8Error::InvalidPublicKeyExplicit));
247 }
248
249 #[test]
250 fn decode_bad_public_key_prefix() {
251 let mut der = decode_hex(TEST_DER_HEX);
252 der[73] = 0x02;
253 assert_eq!(decode_p256_pkcs8_der(&der), Err(Pkcs8Error::InvalidPublicKeyPrefix));
254 }
255
256 #[test]
257 fn encode_round_trip_random_keys() {
258 for _ in 0..10 {
259 let priv_key: [u8; 32] = rand::random();
260 let key = match PrivateKey::from_bytes(&priv_key) {
261 Ok(k) => k,
262 Err(_) => continue,
263 };
264 let der = encode_p256_pkcs8_der(&key).unwrap();
265 let decoded = decode_p256_pkcs8_der(&der).unwrap();
266 assert_eq!(decoded.to_bytes(), key.to_bytes());
267 assert_eq!(decoded.public_key().to_bytes().len(), 65);
268 assert_eq!(decoded.public_key().to_bytes()[0], 0x04);
269 }
270 }
271
272 #[test]
273 fn encode_rejects_invalid_key() {
274 let invalid = [0u8; 32];
275 assert!(PrivateKey::from_bytes(&invalid).is_err());
276 }
277}