crypto_wasi/
key.rs

1use crate::{
2    raw::{self, CRYPTO_ERRNO_UNSUPPORTED_ALGORITHM},
3    CryptoErrno, NONE_OPTS,
4};
5use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
6
7/// Setting encoding format for export [PublicKey] and [PrivateKey]
8#[derive(Clone, Copy, PartialEq, Eq)]
9pub enum KeyEncodingFormat {
10    Pem,
11    Der,
12    /// When JWK encoding format was selected, all other encoding options are ignored.
13    Jwk,
14}
15
16#[derive(Clone, Copy, PartialEq, Eq)]
17pub(crate) enum CurveKind {
18    Prime256v1,
19    Secp256k1,
20    Secp384r1,
21}
22
23const OID_CURVE_PRIME256V1: &str = "1.2.840.10045.3.1.7";
24const OID_CURVE_SECP256K1: &str = "1.3.132.0.10";
25const OID_CURVE_SECP384R1: &str = "1.3.132.0.34";
26const OID_ED25519: &str = "1.3.101.112";
27const OID_X25519: &str = "1.3.101.110";
28
29#[derive(Clone, Copy, PartialEq, Eq)]
30pub(crate) enum DigestKind {
31    SHA256,
32    SHA384,
33    SHA512,
34}
35
36/// Supported algorithm list:
37///
38/// - "ECDSA_P256_SHA256" prime256v1 (curve name used in nodejs)
39/// - "ECDSA_K256_SHA256" secp256k1
40/// - "ECDSA_P384_SHA384" secp384r1
41/// - "ED25519"
42/// - "RSA_PKCS1_2048_SHA256"
43/// - "RSA_PKCS1_2048_SHA384"
44/// - "RSA_PKCS1_2048_SHA512"
45/// - "RSA_PKCS1_3072_SHA384"
46/// - "RSA_PKCS1_3072_SHA512"
47/// - "RSA_PKCS1_4096_SHA512"
48/// - "RSA_PSS_2048_SHA256"
49/// - "RSA_PSS_2048_SHA384"
50/// - "RSA_PSS_2048_SHA512"
51/// - "RSA_PSS_3072_SHA384"
52/// - "RSA_PSS_3072_SHA512"
53/// - "RSA_PSS_4096_SHA512"
54/// - "X25519"
55#[derive(Clone, Copy, PartialEq, Eq)]
56pub(crate) enum AlgoKind {
57    Ed,
58    Ec(CurveKind),
59    Rsa(i32, DigestKind),
60    RsaPss(i32, DigestKind),
61    X25519,
62}
63
64impl AlgoKind {
65    fn from_str(algo: &str) -> Result<Self, CryptoErrno> {
66        let algo = algo.to_uppercase();
67        let mut iter = algo.split('_');
68        let a = iter.next();
69        let b = iter.next();
70        let c = iter.next();
71        let d = iter.next();
72        match (a, b, c, d) {
73            (Some("ED25519"), _, _, _) => Ok(AlgoKind::Ed),
74            (Some("X25519"), _, _, _) => Ok(AlgoKind::X25519),
75            (Some("ECDSA"), Some("P256"), _, _) => Ok(AlgoKind::Ec(CurveKind::Prime256v1)),
76            (Some("ECDSA"), Some("K256"), _, _) => Ok(AlgoKind::Ec(CurveKind::Secp256k1)),
77            (Some("ECDSA"), Some("P384"), _, _) => Ok(AlgoKind::Ec(CurveKind::Secp384r1)),
78            (Some("RSA"), Some("PKCS1"), Some("2048"), None | Some("SHA256")) => {
79                Ok(AlgoKind::Rsa(2048, DigestKind::SHA256))
80            }
81            (Some("RSA"), Some("PKCS1"), Some("2048"), Some("SHA384")) => {
82                Ok(AlgoKind::Rsa(2048, DigestKind::SHA384))
83            }
84            (Some("RSA"), Some("PKCS1"), Some("2048"), Some("SHA512")) => {
85                Ok(AlgoKind::Rsa(2048, DigestKind::SHA512))
86            }
87            (Some("RSA"), Some("PKCS1"), Some("3072"), None | Some("SHA384")) => {
88                Ok(AlgoKind::Rsa(3072, DigestKind::SHA384))
89            }
90            (Some("RSA"), Some("PKCS1"), Some("3072"), Some("SHA512")) => {
91                Ok(AlgoKind::Rsa(3072, DigestKind::SHA512))
92            }
93            (Some("RSA"), Some("PKCS1"), Some("4096"), None | Some("SHA512")) => {
94                Ok(AlgoKind::Rsa(4096, DigestKind::SHA512))
95            }
96            (Some("RSA"), Some("PSS"), Some("2048"), None | Some("SHA256")) => {
97                Ok(AlgoKind::RsaPss(2048, DigestKind::SHA256))
98            }
99            (Some("RSA"), Some("PSS"), Some("2048"), Some("SHA384")) => {
100                Ok(AlgoKind::RsaPss(2048, DigestKind::SHA384))
101            }
102            (Some("RSA"), Some("PSS"), Some("2048"), Some("SHA512")) => {
103                Ok(AlgoKind::RsaPss(2048, DigestKind::SHA512))
104            }
105            (Some("RSA"), Some("PSS"), Some("3072"), None | Some("SHA384")) => {
106                Ok(AlgoKind::RsaPss(3072, DigestKind::SHA384))
107            }
108            (Some("RSA"), Some("PSS"), Some("3072"), Some("SHA512")) => {
109                Ok(AlgoKind::RsaPss(3072, DigestKind::SHA512))
110            }
111            (Some("RSA"), Some("PSS"), Some("4096"), None | Some("SHA512")) => {
112                Ok(AlgoKind::RsaPss(4096, DigestKind::SHA512))
113            }
114            _ => Err(raw::CRYPTO_ERRNO_UNSUPPORTED_ALGORITHM),
115        }
116    }
117
118    pub(crate) fn to_str(&self) -> &'static str {
119        match self {
120            AlgoKind::Ed => "ED25519",
121            AlgoKind::X25519 => "X25519",
122            AlgoKind::Ec(curve) => match curve {
123                CurveKind::Prime256v1 => "ECDSA_P256_SHA256",
124                CurveKind::Secp256k1 => "ECDSA_K256_SHA256",
125                CurveKind::Secp384r1 => "ECDSA_P384_SHA384",
126            },
127            AlgoKind::Rsa(len, digest) => match len {
128                2048 => match digest {
129                    DigestKind::SHA256 => "RSA_PKCS1_2048_SHA256",
130                    DigestKind::SHA384 => "RSA_PKCS1_2048_SHA384",
131                    DigestKind::SHA512 => "RSA_PKCS1_2048_SHA512",
132                },
133                3072 => match digest {
134                    DigestKind::SHA384 => "RSA_PKCS1_3072_SHA384",
135                    DigestKind::SHA512 => "RSA_PKCS1_3072_SHA512",
136                    _ => unreachable!(),
137                },
138                4096 => match digest {
139                    DigestKind::SHA512 => "RSA_PKCS1_4096_SHA512",
140                    _ => unreachable!(),
141                },
142                _ => unreachable!(),
143            },
144            AlgoKind::RsaPss(len, digest) => match len {
145                2048 => match digest {
146                    DigestKind::SHA256 => "RSA_PSS_2048_SHA256",
147                    DigestKind::SHA384 => "RSA_PSS_2048_SHA384",
148                    DigestKind::SHA512 => "RSA_PSS_2048_SHA512",
149                },
150                3072 => match digest {
151                    DigestKind::SHA384 => "RSA_PSS_3072_SHA384",
152                    DigestKind::SHA512 => "RSA_PSS_3072_SHA512",
153                    _ => unreachable!(),
154                },
155                4096 => match digest {
156                    DigestKind::SHA512 => "RSA_PSS_4096_SHA512",
157                    _ => unreachable!(),
158                },
159                _ => unreachable!(),
160            },
161        }
162    }
163}
164
165/// `crypto.KeyObject` for public (asymmetric) keys
166pub struct PublicKey {
167    pub(crate) handle: raw::Publickey,
168    pub(crate) algo: AlgoKind,
169}
170
171/// Setting encoding type for export [PublicKey]
172#[derive(Clone, Copy, PartialEq, Eq)]
173pub enum PublicKeyEncodingType {
174    Spki,
175    Pkcs1,
176}
177
178fn publickey_export(
179    pk: raw::Publickey,
180    encoding: raw::PublickeyEncoding,
181) -> Result<Vec<u8>, CryptoErrno> {
182    let res = unsafe {
183        let arr = raw::publickey_export(pk, encoding)?;
184        let len = raw::array_output_len(arr)?;
185        let mut buf = vec![0; len];
186        raw::array_output_pull(arr, buf.as_mut_ptr(), buf.len())?;
187        buf
188    };
189    Ok(res)
190}
191
192fn secretkey_export(
193    sk: raw::Secretkey,
194    encoding: raw::SecretkeyEncoding,
195) -> Result<Vec<u8>, CryptoErrno> {
196    let res = unsafe {
197        let arr = raw::secretkey_export(sk, encoding)?;
198        let len = raw::array_output_len(arr)?;
199        let mut buf = vec![0; len];
200        raw::array_output_pull(arr, buf.as_mut_ptr(), buf.len())?;
201        buf
202    };
203    Ok(res)
204}
205
206impl PublicKey {
207    pub fn export(
208        &self,
209        kind: PublicKeyEncodingType,
210        format: KeyEncodingFormat,
211    ) -> Result<Vec<u8>, CryptoErrno> {
212        // for rsa, rsa-pss support der-spki(pkcs8), pem-spki(pem)
213        // for ecdsa support der-spki(pkcs8), pem-spki(pem), bin-raw(sec)
214        // for eddsa support bin-raw(raw)
215        match (self.algo, kind, format) {
216            (AlgoKind::Rsa(_, _), PublicKeyEncodingType::Spki, KeyEncodingFormat::Pem)
217            | (AlgoKind::RsaPss(_, _), PublicKeyEncodingType::Spki, KeyEncodingFormat::Pem)
218            | (AlgoKind::Ec(_), PublicKeyEncodingType::Spki, KeyEncodingFormat::Pem) => {
219                publickey_export(self.handle, raw::PUBLICKEY_ENCODING_PEM)
220            }
221            (AlgoKind::Rsa(_, _), PublicKeyEncodingType::Spki, KeyEncodingFormat::Der)
222            | (AlgoKind::RsaPss(_, _), PublicKeyEncodingType::Spki, KeyEncodingFormat::Der)
223            | (AlgoKind::Ec(_), PublicKeyEncodingType::Spki, KeyEncodingFormat::Der) => {
224                publickey_export(self.handle, raw::PUBLICKEY_ENCODING_PKCS8)
225            }
226            (AlgoKind::Ec(curve), _, KeyEncodingFormat::Jwk) => {
227                let bin = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_SEC)?;
228                let compress_kind = bin[0];
229                // rfc5480, sec1 2.3.3
230                assert!(compress_kind == 0x04, "only support uncompressed form now");
231                let x = URL_SAFE_NO_PAD.encode(&bin[1..33]);
232                let y = URL_SAFE_NO_PAD.encode(&bin[33..65]);
233                let curve_name = match curve {
234                    CurveKind::Prime256v1 => "P-256",
235                    CurveKind::Secp256k1 => "secp256k1",
236                    CurveKind::Secp384r1 => "P-384",
237                };
238                let jwk = format!(r#"{{"x":"{x}","y":"{y}","kty":"EC","crv":"{curve_name}"}}"#);
239                Ok(jwk.into_bytes())
240            }
241            (AlgoKind::Rsa(_, _), _, KeyEncodingFormat::Jwk) => {
242                let der = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_PKCS8)?;
243                let raw = SubjectPublicKeyInfo::from_der(&der)
244                    .unwrap()
245                    .subject_public_key
246                    .as_bytes()
247                    .unwrap();
248                let rsa_pk = RsaPublicKey::from_der(raw).unwrap();
249                let n = URL_SAFE_NO_PAD.encode(rsa_pk.modulus.as_bytes());
250                let e = URL_SAFE_NO_PAD.encode(rsa_pk.public_exponent.as_bytes());
251                let jwk = format!(r#"{{"n":"{n}","e":"{e}","kty":"RSA"}}"#);
252                Ok(jwk.into_bytes())
253            }
254            (AlgoKind::RsaPss(_, _), _, KeyEncodingFormat::Jwk) => {
255                Err(raw::CRYPTO_ERRNO_UNSUPPORTED_ENCODING)
256            }
257            (AlgoKind::Ed, PublicKeyEncodingType::Spki, KeyEncodingFormat::Der)
258            | (AlgoKind::Ed, PublicKeyEncodingType::Spki, KeyEncodingFormat::Pem) => {
259                let raw = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_RAW)?;
260                let spki = SubjectPublicKeyInfo {
261                    algorithm: AlgorithmIdentifier {
262                        algorithm: ObjectIdentifier::new(OID_ED25519).unwrap(),
263                        parameters: None,
264                    },
265                    subject_public_key: BitStringRef::new(0, &raw).unwrap(),
266                };
267                let der = spki.to_der().unwrap();
268                match format {
269                    KeyEncodingFormat::Der => Ok(der),
270                    KeyEncodingFormat::Pem => Ok(pem::encode(&pem::Pem {
271                        tag: "PUBLIC KEY".to_string(),
272                        contents: der,
273                    })
274                    .into_bytes()),
275                    KeyEncodingFormat::Jwk => unreachable!(),
276                }
277            }
278            (AlgoKind::Ed, _, KeyEncodingFormat::Jwk) => {
279                let raw = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_RAW)?;
280                let x = URL_SAFE_NO_PAD.encode(raw);
281                let jwk = format!(r#"{{"crv":"Ed25519","x":"{x}","kty":"OKP"}}"#);
282                Ok(jwk.into_bytes())
283            }
284            (AlgoKind::Rsa(_, _), PublicKeyEncodingType::Pkcs1, KeyEncodingFormat::Pem)
285            | (AlgoKind::Rsa(_, _), PublicKeyEncodingType::Pkcs1, KeyEncodingFormat::Der) => {
286                let der = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_PKCS8)?;
287                let rsa_pk = SubjectPublicKeyInfo::from_der(&der)
288                    .unwrap()
289                    .subject_public_key
290                    .as_bytes()
291                    .unwrap();
292                match format {
293                    KeyEncodingFormat::Jwk => unreachable!(),
294                    KeyEncodingFormat::Der => Ok(rsa_pk.to_vec()),
295                    KeyEncodingFormat::Pem => Ok(pem::encode(&pem::Pem {
296                        tag: "RSA PUBLIC KEY".to_string(),
297                        contents: rsa_pk.to_vec(),
298                    })
299                    .into_bytes()),
300                }
301            }
302            (_, PublicKeyEncodingType::Pkcs1, _) => Err(raw::CRYPTO_ERRNO_UNSUPPORTED_ENCODING),
303            (AlgoKind::X25519, PublicKeyEncodingType::Spki, KeyEncodingFormat::Pem)
304            | (AlgoKind::X25519, PublicKeyEncodingType::Spki, KeyEncodingFormat::Der) => {
305                let raw = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_RAW)?;
306                let skpi = SubjectPublicKeyInfo {
307                    algorithm: AlgorithmIdentifier {
308                        algorithm: ObjectIdentifier::new(OID_X25519).unwrap(),
309                        parameters: None,
310                    },
311                    subject_public_key: BitStringRef::new(0, &raw).unwrap(),
312                };
313                let der = skpi.to_der().unwrap();
314                if format == KeyEncodingFormat::Der {
315                    Ok(der)
316                } else {
317                    Ok(pem::encode(&pem::Pem {
318                        tag: "PUBLIC KEY".to_string(),
319                        contents: der,
320                    })
321                    .into_bytes())
322                }
323            }
324            (AlgoKind::X25519, PublicKeyEncodingType::Spki, KeyEncodingFormat::Jwk) => {
325                let raw = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_RAW)?;
326                let x = URL_SAFE_NO_PAD.encode(raw);
327                let jwk = format!(r#"{{"crv":"X25519","x":"{x}","kty":"OKP"}}"#);
328                Ok(jwk.into_bytes())
329            }
330        }
331    }
332
333    pub(crate) fn cast_to_dh_key(&self) -> Result<PublicKey, CryptoErrno> {
334        match self.algo {
335            AlgoKind::Ec(CurveKind::Prime256v1) | AlgoKind::Ec(CurveKind::Secp384r1) => unsafe {
336                let raw = publickey_export(self.handle, raw::PUBLICKEY_ENCODING_PEM)?;
337                let pk = raw::publickey_import(
338                    raw::ALGORITHM_TYPE_KEY_EXCHANGE,
339                    if self.algo == AlgoKind::Ec(CurveKind::Prime256v1) {
340                        "P256-SHA256"
341                    } else {
342                        "P384-SHA384"
343                    },
344                    raw.as_ptr(),
345                    raw.len(),
346                    raw::PUBLICKEY_ENCODING_PEM,
347                )?;
348                Ok(PublicKey {
349                    handle: pk,
350                    algo: self.algo,
351                })
352            },
353            _ => Err(CRYPTO_ERRNO_UNSUPPORTED_ALGORITHM),
354        }
355    }
356}
357
358/// `crypto.KeyObject` for private (asymmetric) keys
359pub struct PrivateKey {
360    pub(crate) handle: raw::Secretkey,
361    /// we need store keypair handle because WasmEdge not implemented `keypair_from_pk_and_sk`
362    pub(crate) keypair_handle: raw::Keypair,
363    pub(crate) algo: AlgoKind,
364}
365
366/// Setting encoding type for export [PrivateKey]
367#[derive(Clone, Copy, PartialEq, Eq)]
368pub enum PrivateKeyEncodingType {
369    Pkcs8,
370    Pkcs1,
371    Sec1,
372}
373
374impl PrivateKey {
375    fn get_publickey(&self) -> Result<PublicKey, CryptoErrno> {
376        // let pk = unsafe { raw::publickey_from_secretkey(self.handle) }?;
377        let pk = unsafe { raw::keypair_publickey(self.keypair_handle) }?;
378        Ok(PublicKey {
379            handle: pk,
380            algo: self.algo,
381        })
382    }
383
384    pub fn export(
385        &self,
386        kind: PrivateKeyEncodingType,
387        format: KeyEncodingFormat,
388    ) -> Result<Vec<u8>, CryptoErrno> {
389        // for rsa, rsa-pss support der-spki(pkcs8), pem-spki(pem)
390        // for ecdsa support der-spki(pkcs8), pem-spki(pem), bin-raw(sec)
391        // for eddsa support bin-raw(raw)
392        match (self.algo, kind, format) {
393            (AlgoKind::Ec(_), PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Pem)
394            | (AlgoKind::Rsa(_, _), PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Pem)
395            | (AlgoKind::RsaPss(_, _), PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Pem) => {
396                secretkey_export(self.handle, raw::SECRETKEY_ENCODING_PEM)
397            }
398            (AlgoKind::Ec(_), PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Der)
399            | (AlgoKind::RsaPss(_, _), PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Der) => {
400                secretkey_export(self.handle, raw::SECRETKEY_ENCODING_PKCS8)
401            }
402            (AlgoKind::Rsa(_, _), PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Der) => {
403                let pkcs8 = secretkey_export(self.handle, raw::SECRETKEY_ENCODING_PEM)?;
404                pem::parse(pkcs8)
405                    .map(|p| p.contents)
406                    .or(Err(raw::CRYPTO_ERRNO_ALGORITHM_FAILURE))
407            }
408            (AlgoKind::Ed, PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Pem)
409            | (AlgoKind::Ed, PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Der)
410            | (AlgoKind::X25519, PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Pem)
411            | (AlgoKind::X25519, PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Der) => {
412                let raw = secretkey_export(self.handle, raw::SECRETKEY_ENCODING_RAW)?;
413                let der = PrivateKeyInfo::new(
414                    AlgorithmIdentifier {
415                        algorithm: ObjectIdentifier::new(if self.algo == AlgoKind::Ed {
416                            OID_ED25519
417                        } else {
418                            OID_X25519
419                        })
420                        .unwrap(),
421                        parameters: None,
422                    },
423                    &OctetString::new(raw).unwrap().to_der().unwrap(),
424                )
425                .to_der()
426                .unwrap();
427                match format {
428                    KeyEncodingFormat::Der => Ok(der),
429                    KeyEncodingFormat::Pem => Ok(pem::encode(&pem::Pem {
430                        tag: "PRIVATE KEY".to_string(),
431                        contents: der,
432                    })
433                    .into_bytes()),
434                    KeyEncodingFormat::Jwk => unreachable!(),
435                }
436            }
437            (AlgoKind::Rsa(_, _), PrivateKeyEncodingType::Pkcs1, KeyEncodingFormat::Pem)
438            | (AlgoKind::Rsa(_, _), PrivateKeyEncodingType::Pkcs1, KeyEncodingFormat::Der) => {
439                let pkcs8 = self.export(PrivateKeyEncodingType::Pkcs8, KeyEncodingFormat::Der)?;
440                let raw = PrivateKeyInfo::from_der(&pkcs8).unwrap().private_key;
441                match format {
442                    KeyEncodingFormat::Der => Ok(raw.to_vec()),
443                    KeyEncodingFormat::Pem => Ok(pem::encode(&pem::Pem {
444                        tag: "RSA PRIVATE KEY".to_string(),
445                        contents: raw.to_vec(),
446                    })
447                    .into_bytes()),
448                    KeyEncodingFormat::Jwk => unreachable!(),
449                }
450            }
451            (AlgoKind::Ec(curve), PrivateKeyEncodingType::Sec1, KeyEncodingFormat::Pem)
452            | (AlgoKind::Ec(curve), PrivateKeyEncodingType::Sec1, KeyEncodingFormat::Der) => {
453                let res = secretkey_export(self.handle, raw::SECRETKEY_ENCODING_RAW)?;
454                let curve = match curve {
455                    CurveKind::Prime256v1 => OID_CURVE_PRIME256V1,
456                    CurveKind::Secp256k1 => OID_CURVE_SECP256K1,
457                    CurveKind::Secp384r1 => OID_CURVE_SECP384R1,
458                };
459                let pk = self.get_publickey()?;
460                // the got is actually the public_key content in spki, not sure if it's a bug or feature
461                let pk_data = publickey_export(pk.handle, raw::PUBLICKEY_ENCODING_SEC)?;
462                let sec1 = EcPrivateKey {
463                    private_key: &res,
464                    parameters: Some(EcParameters::NamedCurve(curve.parse().unwrap())),
465                    public_key: Some(&pk_data),
466                };
467                let der = sec1.to_der().unwrap();
468                match format {
469                    KeyEncodingFormat::Pem => Ok(pem::encode(&pem::Pem {
470                        tag: "EC PRIVATE KEY".to_string(),
471                        contents: der,
472                    })
473                    .into_bytes()),
474                    KeyEncodingFormat::Der => Ok(der),
475                    KeyEncodingFormat::Jwk => unreachable!(),
476                }
477            }
478            (AlgoKind::Ed, _, KeyEncodingFormat::Jwk)
479            | (AlgoKind::X25519, _, KeyEncodingFormat::Jwk) => {
480                let raw = secretkey_export(self.handle, raw::SECRETKEY_ENCODING_RAW)?;
481                let d = URL_SAFE_NO_PAD.encode(raw);
482                let pk = self.get_publickey()?;
483                let pkraw = publickey_export(pk.handle, raw::PUBLICKEY_ENCODING_RAW)?;
484                let x = URL_SAFE_NO_PAD.encode(pkraw);
485                let jwk = format!(
486                    r#"{{"crv":"{}","d":"{d}","x":"{x}","kty":"OKP"}}"#,
487                    if self.algo == AlgoKind::X25519 {
488                        "X25519"
489                    } else {
490                        "Ed25519"
491                    }
492                );
493                Ok(jwk.into_bytes())
494            }
495            (AlgoKind::Ec(curve), _, KeyEncodingFormat::Jwk) => {
496                let bins = secretkey_export(self.handle, raw::SECRETKEY_ENCODING_RAW)?;
497                let curve_name = match curve {
498                    CurveKind::Prime256v1 => "P-256",
499                    CurveKind::Secp256k1 => "secp256k1",
500                    CurveKind::Secp384r1 => "P-384",
501                };
502                let pk = self.get_publickey()?;
503                let binp = publickey_export(pk.handle, raw::PUBLICKEY_ENCODING_SEC)?;
504                let compress_kind = binp[0];
505                // rfc5480, sec1 2.3.3
506                // assert!(compress_kind == 0x04, "only support uncompressed form now");
507                if compress_kind != 0x04 {
508                    Err(raw::CRYPTO_ERRNO_NOT_IMPLEMENTED)
509                } else {
510                    let d = URL_SAFE_NO_PAD.encode(bins);
511                    let x = URL_SAFE_NO_PAD.encode(&binp[1..33]);
512                    let y = URL_SAFE_NO_PAD.encode(&binp[33..65]);
513                    let jwk = format!(
514                        r#"{{"x":"{x}","y":"{y}","kty":"EC","crv":"{curve_name}","d":"{d}"}}"#
515                    );
516                    Ok(jwk.into_bytes())
517                }
518            }
519            (AlgoKind::Rsa(_, _), _, KeyEncodingFormat::Jwk) => {
520                let pkcs1 = self.export(PrivateKeyEncodingType::Pkcs1, KeyEncodingFormat::Der)?;
521                let raw = RsaPrivateKey::from_der(&pkcs1).unwrap();
522                let n = URL_SAFE_NO_PAD.encode(raw.modulus.as_bytes());
523                let e = URL_SAFE_NO_PAD.encode(raw.public_exponent.as_bytes());
524                let d = URL_SAFE_NO_PAD.encode(raw.private_exponent.as_bytes());
525                let p = URL_SAFE_NO_PAD.encode(raw.prime1.as_bytes());
526                let q = URL_SAFE_NO_PAD.encode(raw.prime2.as_bytes());
527                let dp = URL_SAFE_NO_PAD.encode(raw.exponent1.as_bytes());
528                let dq = URL_SAFE_NO_PAD.encode(raw.exponent2.as_bytes());
529                let qi = URL_SAFE_NO_PAD.encode(raw.coefficient.as_bytes());
530                let jwk = format!(
531                    r#"{{"n":"{n}","e":"{e}","kty":"RSA","d":"{d}","p":"{p}","q":"{q}","dp":"{dp}","dq":"{dq}","qi":"{qi}"}}"#
532                );
533                Ok(jwk.into_bytes())
534            }
535            (AlgoKind::Rsa(_, _), PrivateKeyEncodingType::Sec1, _)
536            | (AlgoKind::RsaPss(_, _), PrivateKeyEncodingType::Sec1, _)
537            | (AlgoKind::Ed, PrivateKeyEncodingType::Sec1, _)
538            | (AlgoKind::RsaPss(_, _), _, KeyEncodingFormat::Jwk)
539            | (AlgoKind::Ed, PrivateKeyEncodingType::Pkcs1, _)
540            | (AlgoKind::Ec(_), PrivateKeyEncodingType::Pkcs1, _)
541            | (AlgoKind::RsaPss(_, _), PrivateKeyEncodingType::Pkcs1, _)
542            | (AlgoKind::X25519, PrivateKeyEncodingType::Pkcs1 | PrivateKeyEncodingType::Sec1, _) => {
543                Err(raw::CRYPTO_ERRNO_UNSUPPORTED_ENCODING)
544            }
545        }
546    }
547
548    pub fn get_asymmetric_key_type(&self) -> &'static str {
549        match self.algo {
550            AlgoKind::Ed => "ed25519",
551            AlgoKind::Ec(_) => "ec",
552            AlgoKind::Rsa(_, _) => "rsa",
553            AlgoKind::RsaPss(_, _) => "rsa-pss",
554            AlgoKind::X25519 => "x25519",
555        }
556    }
557
558    pub(crate) fn cast_to_dh_key(&self) -> Result<PrivateKey, CryptoErrno> {
559        match self.algo {
560            AlgoKind::Ec(CurveKind::Prime256v1) | AlgoKind::Ec(CurveKind::Secp384r1) => unsafe {
561                let raw = secretkey_export(self.handle, raw::SECRETKEY_ENCODING_RAW)?;
562                let sk = raw::secretkey_import(
563                    raw::ALGORITHM_TYPE_KEY_EXCHANGE,
564                    if self.algo == AlgoKind::Ec(CurveKind::Prime256v1) {
565                        "P256-SHA256"
566                    } else {
567                        "P384-SHA384"
568                    },
569                    raw.as_ptr(),
570                    raw.len(),
571                    raw::SECRETKEY_ENCODING_RAW,
572                )?;
573                // we can't reconstruct a keypair because WasmEdge not implemented `keypair_from_pk_and_sk`
574                Ok(PrivateKey {
575                    handle: sk,
576                    keypair_handle: 0,
577                    algo: self.algo,
578                })
579            },
580            _ => Err(CRYPTO_ERRNO_UNSUPPORTED_ALGORITHM),
581        }
582    }
583}
584
585/// Generates a new asymmetric key pair of the given `algorithm`
586///
587/// Unlike nodejs, it cannot directly specify the export parameter
588/// and please use the [`PublicKey::export()`] and [`PrivateKey::export()`] function
589///
590/// Supported algorithm list:
591/// - "ECDSA_P256_SHA256" prime256v1 (curve name used in nodejs)
592/// - "ECDSA_K256_SHA256" secp256k1
593/// - "ECDSA_P384_SHA384" secp384r1
594/// - "ED25519"
595/// - "RSA_PKCS1_2048_SHA256"
596/// - "RSA_PKCS1_2048_SHA384"
597/// - "RSA_PKCS1_2048_SHA512"
598/// - "RSA_PKCS1_3072_SHA384"
599/// - "RSA_PKCS1_3072_SHA512"
600/// - "RSA_PKCS1_4096_SHA512"
601/// - "RSA_PSS_2048_SHA256"
602/// - "RSA_PSS_2048_SHA384"
603/// - "RSA_PSS_2048_SHA512"
604/// - "RSA_PSS_3072_SHA384"
605/// - "RSA_PSS_3072_SHA512"
606/// - "RSA_PSS_4096_SHA512"
607pub fn generate_key_pair(algorithm: &str) -> Result<(PublicKey, PrivateKey), CryptoErrno> {
608    let algo = AlgoKind::from_str(algorithm)?;
609    let (pk, sk, kp) = unsafe {
610        let kp = raw::keypair_generate(
611            if matches!(algo, AlgoKind::X25519) {
612                raw::ALGORITHM_TYPE_KEY_EXCHANGE
613            } else {
614                raw::ALGORITHM_TYPE_SIGNATURES
615            },
616            algorithm,
617            NONE_OPTS,
618        )?;
619        (raw::keypair_publickey(kp)?, raw::keypair_secretkey(kp)?, kp)
620    };
621    Ok((
622        PublicKey { handle: pk, algo },
623        PrivateKey {
624            handle: sk,
625            keypair_handle: kp,
626            algo,
627        },
628    ))
629}
630
631/*
632Copyright (c) 2020-2023 The RustCrypto Project Developers
633
634Permission is hereby granted, free of charge, to any
635person obtaining a copy of this software and associated
636documentation files (the "Software"), to deal in the
637Software without restriction, including without
638limitation the rights to use, copy, modify, merge,
639publish, distribute, sublicense, and/or sell copies of
640the Software, and to permit persons to whom the Software
641is furnished to do so, subject to the following
642conditions:
643
644The above copyright notice and this permission notice
645shall be included in all copies or substantial portions
646of the Software.
647
648THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
649ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
650TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
651PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
652SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
653CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
654OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
655IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
656DEALINGS IN THE SOFTWARE.
657*/
658
659use der::{
660    asn1::{
661        AnyRef, BitStringRef, ContextSpecific, ContextSpecificRef, ObjectIdentifier, OctetString,
662        OctetStringRef, UintRef,
663    },
664    Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, Tag,
665    TagMode, TagNumber, Writer,
666};
667
668/// X.509 `AlgorithmIdentifier`.
669#[derive(Copy, Clone, Debug, Eq, PartialEq)]
670struct AlgorithmIdentifier<'a> {
671    /// This field contains an ASN.1 `OBJECT IDENTIFIER`, a.k.a. OID.
672    pub algorithm: ObjectIdentifier,
673
674    /// This field is `OPTIONAL` and contains the ASN.1 `ANY` type, which
675    /// in this example allows arbitrary algorithm-defined parameters.
676    pub parameters: Option<AnyRef<'a>>,
677}
678
679impl<'a> DecodeValue<'a> for AlgorithmIdentifier<'a> {
680    fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
681        // The `der::Decoder::Decode` method can be used to decode any
682        // type which impls the `Decode` trait, which is impl'd for
683        // all of the ASN.1 built-in types in the `der` crate.
684        //
685        // Note that if your struct's fields don't contain an ASN.1
686        // built-in type specifically, there are also helper methods
687        // for all of the built-in types supported by this library
688        // which can be used to select a specific type.
689        //
690        // For example, another way of decoding this particular field,
691        // which contains an ASN.1 `OBJECT IDENTIFIER`, is by calling
692        // `decoder.oid()`. Similar methods are defined for other
693        // ASN.1 built-in types.
694        let algorithm = reader.decode()?;
695
696        // This field contains an ASN.1 `OPTIONAL` type. The `der` crate
697        // maps this directly to Rust's `Option` type and provides
698        // impls of the `Decode` and `Encode` traits for `Option`.
699        // To explicitly request an `OPTIONAL` type be decoded, use the
700        // `decoder.optional()` method.
701        let parameters = reader.decode()?;
702
703        // The value returned from the provided `FnOnce` will be
704        // returned from the `any.sequence(...)` call above.
705        // Note that the entire sequence body *MUST* be consumed
706        // or an error will be returned.
707        Ok(Self {
708            algorithm,
709            parameters,
710        })
711    }
712}
713
714impl<'a> ::der::EncodeValue for AlgorithmIdentifier<'a> {
715    fn value_len(&self) -> ::der::Result<::der::Length> {
716        self.algorithm.encoded_len()? + self.parameters.encoded_len()?
717    }
718
719    fn encode_value(&self, writer: &mut impl ::der::Writer) -> ::der::Result<()> {
720        self.algorithm.encode(writer)?;
721        self.parameters.encode(writer)?;
722        Ok(())
723    }
724}
725
726impl<'a> Sequence<'a> for AlgorithmIdentifier<'a> {}
727
728/// X.509 `SubjectPublicKeyInfo` (SPKI)
729#[derive(Copy, Clone, Debug, Eq, PartialEq)]
730struct SubjectPublicKeyInfo<'a> {
731    /// X.509 `AlgorithmIdentifier`
732    algorithm: AlgorithmIdentifier<'a>,
733
734    /// Public key data
735    subject_public_key: BitStringRef<'a>,
736}
737
738impl<'a> DecodeValue<'a> for SubjectPublicKeyInfo<'a> {
739    fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
740        let algorithm = reader.decode()?;
741        let subject_public_key = reader.decode()?;
742        Ok(Self {
743            algorithm,
744            subject_public_key,
745        })
746    }
747}
748
749impl<'a> EncodeValue for SubjectPublicKeyInfo<'a> {
750    fn value_len(&self) -> der::Result<Length> {
751        self.algorithm.encoded_len()? + self.subject_public_key.encoded_len()?
752    }
753
754    fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
755        self.algorithm.encode(encoder)?;
756        self.subject_public_key.encode(encoder)
757    }
758}
759
760impl<'a> Sequence<'a> for SubjectPublicKeyInfo<'a> {}
761
762/// Elliptic curve parameters as described in
763/// [RFC5480 Section 2.1.1](https://datatracker.ietf.org/doc/html/rfc5480#section-2.1.1):
764///
765/// ```text
766/// ECParameters ::= CHOICE {
767///   namedCurve         OBJECT IDENTIFIER
768///   -- implicitCurve   NULL
769///   -- specifiedCurve  SpecifiedECDomain
770/// }
771///   -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
772///   -- Details for SpecifiedECDomain can be found in [X9.62].
773///   -- Any future additions to this CHOICE should be coordinated
774///   -- with ANSI X9.
775/// ```
776#[derive(Copy, Clone, Debug, Eq, PartialEq)]
777enum EcParameters {
778    /// Elliptic curve named by a particular OID.
779    ///
780    /// > namedCurve identifies all the required values for a particular
781    /// > set of elliptic curve domain parameters to be represented by an
782    /// > object identifier.
783    NamedCurve(ObjectIdentifier),
784}
785
786impl<'a> DecodeValue<'a> for EcParameters {
787    fn decode_value<R: Reader<'a>>(decoder: &mut R, header: Header) -> der::Result<Self> {
788        ObjectIdentifier::decode_value(decoder, header).map(Self::NamedCurve)
789    }
790}
791
792impl FixedTag for EcParameters {
793    const TAG: Tag = Tag::ObjectIdentifier;
794}
795
796impl EncodeValue for EcParameters {
797    fn value_len(&self) -> der::Result<Length> {
798        match self {
799            Self::NamedCurve(oid) => oid.value_len(),
800        }
801    }
802
803    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
804        match self {
805            Self::NamedCurve(oid) => oid.encode_value(writer),
806        }
807    }
808}
809
810/// SEC1 elliptic curve private key.
811///
812/// Described in [SEC1: Elliptic Curve Cryptography (Version 2.0)]
813/// Appendix C.4 (p.108) and also [RFC5915 Section 3]:
814///
815/// ```text
816/// ECPrivateKey ::= SEQUENCE {
817///   version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
818///   privateKey     OCTET STRING,
819///   parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
820///   publicKey  [1] BIT STRING OPTIONAL
821/// }
822/// ```
823///
824/// When encoded as PEM (text), keys in this format begin with the following:
825///
826/// ```text
827/// -----BEGIN EC PRIVATE KEY-----
828/// ```
829///
830/// [SEC1: Elliptic Curve Cryptography (Version 2.0)]: https://www.secg.org/sec1-v2.pdf
831/// [RFC5915 Section 3]: https://datatracker.ietf.org/doc/html/rfc5915#section-3
832#[derive(Clone)]
833struct EcPrivateKey<'a> {
834    /// Private key data.
835    private_key: &'a [u8],
836
837    /// Elliptic curve parameters.
838    parameters: Option<EcParameters>,
839
840    /// Public key data, optionally available if version is V2.
841    public_key: Option<&'a [u8]>,
842}
843
844/// `ECPrivateKey` version.
845///
846/// From [RFC5913 Section 3]:
847/// > version specifies the syntax version number of the elliptic curve
848/// > private key structure.  For this version of the document, it SHALL
849/// > be set to ecPrivkeyVer1, which is of type INTEGER and whose value
850/// > is one (1).
851///
852/// [RFC5915 Section 3]: https://datatracker.ietf.org/doc/html/rfc5915#section-3
853const VERSION: u8 = 1;
854
855/// Context-specific tag number for the elliptic curve parameters.
856const EC_PARAMETERS_TAG: TagNumber = TagNumber::new(0);
857
858/// Context-specific tag number for the public key.
859const PUBLIC_KEY_TAG: TagNumber = TagNumber::new(1);
860
861impl<'a> DecodeValue<'a> for EcPrivateKey<'a> {
862    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
863        reader.read_nested(header.length, |reader| {
864            if u8::decode(reader)? != VERSION {
865                return Err(der::Tag::Integer.value_error());
866            }
867
868            let private_key = OctetStringRef::decode(reader)?.as_bytes();
869            let parameters = reader.context_specific(EC_PARAMETERS_TAG, TagMode::Explicit)?;
870            let public_key = reader
871                .context_specific::<BitStringRef<'_>>(PUBLIC_KEY_TAG, TagMode::Explicit)?
872                .map(|bs| bs.as_bytes().ok_or_else(|| Tag::BitString.value_error()))
873                .transpose()?;
874
875            Ok(EcPrivateKey {
876                private_key,
877                parameters,
878                public_key,
879            })
880        })
881    }
882}
883
884impl<'a> EcPrivateKey<'a> {
885    fn context_specific_parameters(&self) -> Option<ContextSpecificRef<'_, EcParameters>> {
886        self.parameters.as_ref().map(|params| ContextSpecificRef {
887            tag_number: EC_PARAMETERS_TAG,
888            tag_mode: TagMode::Explicit,
889            value: params,
890        })
891    }
892
893    fn context_specific_public_key(
894        &self,
895    ) -> der::Result<Option<ContextSpecific<BitStringRef<'a>>>> {
896        self.public_key
897            .map(|pk| {
898                BitStringRef::from_bytes(pk).map(|value| ContextSpecific {
899                    tag_number: PUBLIC_KEY_TAG,
900                    tag_mode: TagMode::Explicit,
901                    value,
902                })
903            })
904            .transpose()
905    }
906}
907
908impl<'a> EncodeValue for EcPrivateKey<'a> {
909    fn value_len(&self) -> der::Result<Length> {
910        VERSION.encoded_len()?
911            + OctetStringRef::new(self.private_key)?.encoded_len()?
912            + self.context_specific_parameters().encoded_len()?
913            + self.context_specific_public_key()?.encoded_len()?
914    }
915
916    fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
917        VERSION.encode(encoder)?;
918        OctetStringRef::new(self.private_key)?.encode(encoder)?;
919        self.context_specific_parameters().encode(encoder)?;
920        self.context_specific_public_key()?.encode(encoder)
921    }
922}
923
924impl<'a> Sequence<'a> for EcPrivateKey<'a> {}
925
926/// PKCS#1 RSA Public Keys as defined in [RFC 8017 Appendix 1.1].
927///
928/// ASN.1 structure containing a serialized RSA public key:
929///
930/// ```text
931/// RSAPublicKey ::= SEQUENCE {
932///     modulus           INTEGER,  -- n
933///     publicExponent    INTEGER   -- e
934/// }
935/// ```
936///
937/// [RFC 8017 Appendix 1.1]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.1
938#[derive(Copy, Clone, Debug, Eq, PartialEq)]
939struct RsaPublicKey<'a> {
940    /// `n`: RSA modulus
941    pub modulus: UintRef<'a>,
942
943    /// `e`: RSA public exponent
944    pub public_exponent: UintRef<'a>,
945}
946
947impl<'a> DecodeValue<'a> for RsaPublicKey<'a> {
948    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
949        reader.read_nested(header.length, |reader| {
950            Ok(Self {
951                modulus: reader.decode()?,
952                public_exponent: reader.decode()?,
953            })
954        })
955    }
956}
957
958impl EncodeValue for RsaPublicKey<'_> {
959    fn value_len(&self) -> der::Result<Length> {
960        self.modulus.encoded_len()? + self.public_exponent.encoded_len()?
961    }
962
963    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
964        self.modulus.encode(writer)?;
965        self.public_exponent.encode(writer)?;
966        Ok(())
967    }
968}
969
970impl<'a> Sequence<'a> for RsaPublicKey<'a> {}
971
972/// Version identifier for PKCS#8 documents.
973///
974/// (RFC 5958 designates `0` and `1` as the only valid versions for PKCS#8 documents)
975#[derive(Clone, Debug, Copy, PartialEq, Eq)]
976enum Version {
977    /// Denotes PKCS#8 v1: no public key field.
978    V1 = 0,
979
980    /// Denotes PKCS#8 v2: `OneAsymmetricKey` with public key field.
981    V2 = 1,
982}
983
984impl Version {
985    /// Is this version expected to have a public key?
986    pub fn has_public_key(self) -> bool {
987        match self {
988            Version::V1 => false,
989            Version::V2 => true,
990        }
991    }
992}
993
994impl<'a> Decode<'a> for Version {
995    fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
996        Version::try_from(u8::decode(decoder)?).map_err(|_| Self::TAG.value_error())
997    }
998}
999
1000impl Encode for Version {
1001    fn encoded_len(&self) -> der::Result<der::Length> {
1002        der::Length::from(1u8).for_tlv()
1003    }
1004
1005    fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
1006        u8::from(*self).encode(writer)
1007    }
1008}
1009
1010impl From<Version> for u8 {
1011    fn from(version: Version) -> Self {
1012        version as u8
1013    }
1014}
1015
1016impl TryFrom<u8> for Version {
1017    type Error = der::Error;
1018    fn try_from(byte: u8) -> Result<Version, der::Error> {
1019        match byte {
1020            0 => Ok(Version::V1),
1021            1 => Ok(Version::V2),
1022            _ => Err(Self::TAG.value_error()),
1023        }
1024    }
1025}
1026
1027impl FixedTag for Version {
1028    const TAG: Tag = Tag::Integer;
1029}
1030
1031/// PKCS#8 `PrivateKeyInfo`.
1032///
1033/// ASN.1 structure containing an `AlgorithmIdentifier`, private key
1034/// data in an algorithm specific format, and optional attributes
1035/// (ignored by this implementation).
1036///
1037/// Supports PKCS#8 v1 as described in [RFC 5208] and PKCS#8 v2 as described
1038/// in [RFC 5958]. PKCS#8 v2 keys include an additional public key field.
1039///
1040/// # PKCS#8 v1 `PrivateKeyInfo`
1041///
1042/// Described in [RFC 5208 Section 5]:
1043///
1044/// ```text
1045/// PrivateKeyInfo ::= SEQUENCE {
1046///         version                   Version,
1047///         privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
1048///         privateKey                PrivateKey,
1049///         attributes           [0]  IMPLICIT Attributes OPTIONAL }
1050///
1051/// Version ::= INTEGER
1052///
1053/// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1054///
1055/// PrivateKey ::= OCTET STRING
1056///
1057/// Attributes ::= SET OF Attribute
1058/// ```
1059///
1060/// # PKCS#8 v2 `OneAsymmetricKey`
1061///
1062/// PKCS#8 `OneAsymmetricKey` as described in [RFC 5958 Section 2]:
1063///
1064/// ```text
1065/// PrivateKeyInfo ::= OneAsymmetricKey
1066///
1067/// OneAsymmetricKey ::= SEQUENCE {
1068///     version                   Version,
1069///     privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
1070///     privateKey                PrivateKey,
1071///     attributes            [0] Attributes OPTIONAL,
1072///     ...,
1073///     [[2: publicKey        [1] PublicKey OPTIONAL ]],
1074///     ...
1075///   }
1076///
1077/// Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2)
1078///
1079/// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1080///
1081/// PrivateKey ::= OCTET STRING
1082///
1083/// Attributes ::= SET OF Attribute
1084///
1085/// PublicKey ::= BIT STRING
1086/// ```
1087///
1088/// [RFC 5208]: https://tools.ietf.org/html/rfc5208
1089/// [RFC 5958]: https://datatracker.ietf.org/doc/html/rfc5958
1090/// [RFC 5208 Section 5]: https://tools.ietf.org/html/rfc5208#section-5
1091/// [RFC 5958 Section 2]: https://datatracker.ietf.org/doc/html/rfc5958#section-2
1092#[derive(Clone)]
1093struct PrivateKeyInfo<'a> {
1094    /// X.509 `AlgorithmIdentifier` for the private key type.
1095    pub algorithm: AlgorithmIdentifier<'a>,
1096
1097    /// Private key data.
1098    pub private_key: &'a [u8],
1099
1100    /// Public key data, optionally available if version is V2.
1101    pub public_key: Option<&'a [u8]>,
1102}
1103
1104impl<'a> PrivateKeyInfo<'a> {
1105    /// Create a new PKCS#8 [`PrivateKeyInfo`] message.
1106    ///
1107    /// This is a helper method which initializes `attributes` and `public_key`
1108    /// to `None`, helpful if you aren't using those.
1109    pub fn new(algorithm: AlgorithmIdentifier<'a>, private_key: &'a [u8]) -> Self {
1110        Self {
1111            algorithm,
1112            private_key,
1113            public_key: None,
1114        }
1115    }
1116
1117    /// Get the PKCS#8 [`Version`] for this structure.
1118    ///
1119    /// [`Version::V1`] if `public_key` is `None`, [`Version::V2`] if `Some`.
1120    pub fn version(&self) -> Version {
1121        if self.public_key.is_some() {
1122            Version::V2
1123        } else {
1124            Version::V1
1125        }
1126    }
1127
1128    /// Get a `BIT STRING` representation of the public key, if present.
1129    fn public_key_bit_string(&self) -> der::Result<Option<ContextSpecific<BitStringRef<'a>>>> {
1130        self.public_key
1131            .map(|pk| {
1132                BitStringRef::from_bytes(pk).map(|value| ContextSpecific {
1133                    tag_number: PUBLIC_KEY_TAG,
1134                    tag_mode: TagMode::Implicit,
1135                    value,
1136                })
1137            })
1138            .transpose()
1139    }
1140}
1141
1142impl<'a> DecodeValue<'a> for PrivateKeyInfo<'a> {
1143    fn decode_value<R: Reader<'a>>(
1144        reader: &mut R,
1145        header: Header,
1146    ) -> der::Result<PrivateKeyInfo<'a>> {
1147        reader.read_nested(header.length, |reader| {
1148            // Parse and validate `version` INTEGER.
1149            let version = Version::decode(reader)?;
1150            let algorithm = reader.decode()?;
1151            let private_key = OctetStringRef::decode(reader)?.into();
1152            let public_key = reader
1153                .context_specific::<BitStringRef<'_>>(PUBLIC_KEY_TAG, TagMode::Implicit)?
1154                .map(|bs| {
1155                    bs.as_bytes()
1156                        .ok_or_else(|| der::Tag::BitString.value_error())
1157                })
1158                .transpose()?;
1159
1160            if version.has_public_key() != public_key.is_some() {
1161                return Err(reader.error(
1162                    der::Tag::ContextSpecific {
1163                        constructed: true,
1164                        number: PUBLIC_KEY_TAG,
1165                    }
1166                    .value_error()
1167                    .kind(),
1168                ));
1169            }
1170
1171            // Ignore any remaining extension fields
1172            while !reader.is_finished() {
1173                reader.decode::<ContextSpecific<AnyRef<'_>>>()?;
1174            }
1175
1176            Ok(Self {
1177                algorithm,
1178                private_key,
1179                public_key,
1180            })
1181        })
1182    }
1183}
1184
1185impl EncodeValue for PrivateKeyInfo<'_> {
1186    fn value_len(&self) -> der::Result<Length> {
1187        self.version().encoded_len()?
1188            + self.algorithm.encoded_len()?
1189            + OctetStringRef::new(self.private_key)?.encoded_len()?
1190            + self.public_key_bit_string()?.encoded_len()?
1191    }
1192
1193    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
1194        self.version().encode(writer)?;
1195        self.algorithm.encode(writer)?;
1196        OctetStringRef::new(self.private_key)?.encode(writer)?;
1197        self.public_key_bit_string()?.encode(writer)?;
1198        Ok(())
1199    }
1200}
1201
1202impl<'a> Sequence<'a> for PrivateKeyInfo<'a> {}
1203
1204/// PKCS#1 OtherPrimeInfo as defined in [RFC 8017 Appendix 1.2].
1205///
1206/// ASN.1 structure containing an additional prime in a multi-prime RSA key.
1207///
1208/// ```text
1209/// OtherPrimeInfo ::= SEQUENCE {
1210///     prime             INTEGER,  -- ri
1211///     exponent          INTEGER,  -- di
1212///     coefficient       INTEGER   -- ti
1213/// }
1214/// ```
1215///
1216/// [RFC 8017 Appendix 1.2]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.2
1217#[derive(Clone)]
1218struct OtherPrimeInfo<'a> {
1219    /// Prime factor `r_i` of `n`, where `i` >= 3.
1220    pub prime: UintRef<'a>,
1221
1222    /// Exponent: `d_i = d mod (r_i - 1)`.
1223    pub exponent: UintRef<'a>,
1224
1225    /// CRT coefficient: `t_i = (r_1 * r_2 * ... * r_(i-1))^(-1) mod r_i`.
1226    pub coefficient: UintRef<'a>,
1227}
1228
1229impl<'a> DecodeValue<'a> for OtherPrimeInfo<'a> {
1230    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
1231        reader.read_nested(header.length, |reader| {
1232            Ok(Self {
1233                prime: reader.decode()?,
1234                exponent: reader.decode()?,
1235                coefficient: reader.decode()?,
1236            })
1237        })
1238    }
1239}
1240
1241impl EncodeValue for OtherPrimeInfo<'_> {
1242    fn value_len(&self) -> der::Result<Length> {
1243        self.prime.encoded_len()? + self.exponent.encoded_len()? + self.coefficient.encoded_len()?
1244    }
1245
1246    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
1247        self.prime.encode(writer)?;
1248        self.exponent.encode(writer)?;
1249        self.coefficient.encode(writer)?;
1250        Ok(())
1251    }
1252}
1253
1254impl<'a> Sequence<'a> for OtherPrimeInfo<'a> {}
1255
1256type OtherPrimeInfos<'a> = Vec<OtherPrimeInfo<'a>>;
1257
1258/// Version identifier for PKCS#1 documents as defined in
1259/// [RFC 8017 Appendix 1.2].
1260///
1261/// > version is the version number, for compatibility with future
1262/// > revisions of this document.  It SHALL be 0 for this version of the
1263/// > document, unless multi-prime is used; in which case, it SHALL be 1.
1264///
1265/// ```text
1266/// Version ::= INTEGER { two-prime(0), multi(1) }
1267///    (CONSTRAINED BY
1268///    {-- version must be multi if otherPrimeInfos present --})
1269/// ```
1270///
1271/// [RFC 8017 Appendix 1.2]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.2
1272#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
1273#[repr(u8)]
1274enum Pkcs1Version {
1275    /// Denotes a `two-prime` key
1276    TwoPrime = 0,
1277
1278    /// Denotes a `multi` (i.e. multi-prime) key
1279    Multi = 1,
1280}
1281
1282impl Pkcs1Version {
1283    /// Is this a multi-prime RSA key?
1284    pub fn is_multi(self) -> bool {
1285        self == Self::Multi
1286    }
1287}
1288
1289impl From<Pkcs1Version> for u8 {
1290    fn from(version: Pkcs1Version) -> Self {
1291        version as u8
1292    }
1293}
1294
1295impl TryFrom<u8> for Pkcs1Version {
1296    type Error = ();
1297    fn try_from(byte: u8) -> Result<Pkcs1Version, ()> {
1298        match byte {
1299            0 => Ok(Pkcs1Version::TwoPrime),
1300            1 => Ok(Pkcs1Version::Multi),
1301            _ => Err(()),
1302        }
1303    }
1304}
1305
1306impl<'a> Decode<'a> for Pkcs1Version {
1307    fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
1308        Pkcs1Version::try_from(u8::decode(decoder)?).map_err(|_| Self::TAG.value_error())
1309    }
1310}
1311
1312impl Encode for Pkcs1Version {
1313    fn encoded_len(&self) -> der::Result<der::Length> {
1314        der::Length::ONE.for_tlv()
1315    }
1316
1317    fn encode(&self, writer: &mut impl Writer) -> der::Result<()> {
1318        u8::from(*self).encode(writer)
1319    }
1320}
1321
1322impl FixedTag for Pkcs1Version {
1323    const TAG: Tag = Tag::Integer;
1324}
1325
1326/// PKCS#1 RSA Private Keys as defined in [RFC 8017 Appendix 1.2].
1327///
1328/// ASN.1 structure containing a serialized RSA private key:
1329///
1330/// ```text
1331/// RSAPrivateKey ::= SEQUENCE {
1332///     version           Version,
1333///     modulus           INTEGER,  -- n
1334///     publicExponent    INTEGER,  -- e
1335///     privateExponent   INTEGER,  -- d
1336///     prime1            INTEGER,  -- p
1337///     prime2            INTEGER,  -- q
1338///     exponent1         INTEGER,  -- d mod (p-1)
1339///     exponent2         INTEGER,  -- d mod (q-1)
1340///     coefficient       INTEGER,  -- (inverse of q) mod p
1341///     otherPrimeInfos   OtherPrimeInfos OPTIONAL
1342/// }
1343/// ```
1344///
1345/// Note: the `version` field is selected automatically based on the absence or
1346/// presence of the `other_prime_infos` field.
1347///
1348/// [RFC 8017 Appendix 1.2]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.2
1349#[derive(Clone)]
1350struct RsaPrivateKey<'a> {
1351    /// `n`: RSA modulus.
1352    pub modulus: UintRef<'a>,
1353
1354    /// `e`: RSA public exponent.
1355    pub public_exponent: UintRef<'a>,
1356
1357    /// `d`: RSA private exponent.
1358    pub private_exponent: UintRef<'a>,
1359
1360    /// `p`: first prime factor of `n`.
1361    pub prime1: UintRef<'a>,
1362
1363    /// `q`: Second prime factor of `n`.
1364    pub prime2: UintRef<'a>,
1365
1366    /// First exponent: `d mod (p-1)`.
1367    pub exponent1: UintRef<'a>,
1368
1369    /// Second exponent: `d mod (q-1)`.
1370    pub exponent2: UintRef<'a>,
1371
1372    /// CRT coefficient: `(inverse of q) mod p`.
1373    pub coefficient: UintRef<'a>,
1374
1375    /// Additional primes `r_3`, ..., `r_u`, in order, if this is a multi-prime
1376    /// RSA key (i.e. `version` is `multi`).
1377    pub other_prime_infos: Option<OtherPrimeInfos<'a>>,
1378}
1379
1380impl<'a> RsaPrivateKey<'a> {
1381    /// Get the public key that corresponds to this [`RsaPrivateKey`].
1382    // used function
1383    // fn public_key(&self) -> RsaPublicKey<'a> {
1384    //     RsaPublicKey {
1385    //         modulus: self.modulus,
1386    //         public_exponent: self.public_exponent,
1387    //     }
1388    // }
1389
1390    /// Get the [`Pkcs1Version`] for this key.
1391    ///
1392    /// Determined by the presence or absence of the
1393    /// [`RsaPrivateKey::other_prime_infos`] field.
1394    fn version(&self) -> Pkcs1Version {
1395        if self.other_prime_infos.is_some() {
1396            Pkcs1Version::Multi
1397        } else {
1398            Pkcs1Version::TwoPrime
1399        }
1400    }
1401}
1402
1403impl<'a> DecodeValue<'a> for RsaPrivateKey<'a> {
1404    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
1405        reader.read_nested(header.length, |reader| {
1406            let version = Pkcs1Version::decode(reader)?;
1407
1408            let result = Self {
1409                modulus: reader.decode()?,
1410                public_exponent: reader.decode()?,
1411                private_exponent: reader.decode()?,
1412                prime1: reader.decode()?,
1413                prime2: reader.decode()?,
1414                exponent1: reader.decode()?,
1415                exponent2: reader.decode()?,
1416                coefficient: reader.decode()?,
1417                other_prime_infos: reader.decode()?,
1418            };
1419
1420            // Ensure version is set correctly for two-prime vs multi-prime key.
1421            if version.is_multi() != result.other_prime_infos.is_some() {
1422                return Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }));
1423            }
1424
1425            Ok(result)
1426        })
1427    }
1428}
1429
1430impl EncodeValue for RsaPrivateKey<'_> {
1431    fn value_len(&self) -> der::Result<Length> {
1432        self.version().encoded_len()?
1433            + self.modulus.encoded_len()?
1434            + self.public_exponent.encoded_len()?
1435            + self.private_exponent.encoded_len()?
1436            + self.prime1.encoded_len()?
1437            + self.prime2.encoded_len()?
1438            + self.exponent1.encoded_len()?
1439            + self.exponent2.encoded_len()?
1440            + self.coefficient.encoded_len()?
1441            + self.other_prime_infos.encoded_len()?
1442    }
1443
1444    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
1445        self.version().encode(writer)?;
1446        self.modulus.encode(writer)?;
1447        self.public_exponent.encode(writer)?;
1448        self.private_exponent.encode(writer)?;
1449        self.prime1.encode(writer)?;
1450        self.prime2.encode(writer)?;
1451        self.exponent1.encode(writer)?;
1452        self.exponent2.encode(writer)?;
1453        self.coefficient.encode(writer)?;
1454        self.other_prime_infos.encode(writer)?;
1455        Ok(())
1456    }
1457}
1458
1459impl<'a> Sequence<'a> for RsaPrivateKey<'a> {}