pgp/packet/
secret_key_parser.rs1use std::io::BufRead;
2
3use log::debug;
4
5use crate::{
6 crypto::public_key::PublicKeyAlgorithm,
7 errors::{ensure, unsupported_err, Result},
8 parsing_reader::BufReadParsing,
9 types::{KeyVersion, PublicParams, SecretParams, Timestamp},
10};
11
12fn parse_pub_priv_fields<B: BufRead>(
14 key_ver: KeyVersion,
15 typ: PublicKeyAlgorithm,
16 pub_len: Option<usize>,
17 mut i: B,
18) -> Result<(PublicParams, SecretParams)> {
19 debug!("KeyVersion: {key_ver:?}, alg: {typ:?}, len {pub_len:?}");
20 let pub_params = match pub_len {
21 Some(pub_len) => {
22 let mut public = i.read_take(pub_len);
24 let pp = PublicParams::try_from_reader(typ, Some(pub_len), &mut public)?;
25
26 ensure!(
27 !public.has_remaining()?,
28 "PublicParams::try_from_reader didn't consume all data"
29 );
30 pp
31 }
32 None => PublicParams::try_from_reader(typ, None, &mut i)?,
33 };
34
35 let v = i.rest()?;
36 debug!("rest: {}", hex::encode(&v));
37
38 let secret_params = SecretParams::from_slice(&v, key_ver, typ, &pub_params)?;
39 Ok((pub_params, secret_params))
40}
41
42fn private_key_parser_v4_v6<B: BufRead>(
43 key_ver: &KeyVersion,
44 mut i: B,
45) -> Result<(
46 KeyVersion,
47 PublicKeyAlgorithm,
48 Timestamp,
49 Option<u16>,
50 PublicParams,
51 SecretParams,
52)> {
53 let created_at = i.read_timestamp()?;
54
55 let alg = i.read_u8().map(PublicKeyAlgorithm::from)?;
56
57 let pub_len = if *key_ver == KeyVersion::V6 {
58 let pub_len = i.read_be_u32()?;
60
61 Some(pub_len as usize)
62 } else {
63 None
64 };
65
66 let params = parse_pub_priv_fields(*key_ver, alg, pub_len, i)?;
67 Ok((*key_ver, alg, created_at, None, params.0, params.1))
68}
69
70fn private_key_parser_v2_v3<B: BufRead>(
71 key_ver: &KeyVersion,
72 mut i: B,
73) -> Result<(
74 KeyVersion,
75 PublicKeyAlgorithm,
76 Timestamp,
77 Option<u16>,
78 PublicParams,
79 SecretParams,
80)> {
81 let created_at = i.read_timestamp()?;
82 let exp = i.read_be_u16()?;
83 let alg = i.read_u8().map(PublicKeyAlgorithm::from)?;
84 let params = parse_pub_priv_fields(*key_ver, alg, None, i)?;
85
86 Ok((*key_ver, alg, created_at, Some(exp), params.0, params.1))
87}
88
89#[allow(clippy::type_complexity)]
92pub(crate) fn parse<B: BufRead>(
93 mut i: B,
94) -> Result<(
95 KeyVersion,
96 PublicKeyAlgorithm,
97 Timestamp,
98 Option<u16>,
99 PublicParams,
100 SecretParams,
101)> {
102 let key_ver = i.read_u8().map(KeyVersion::from)?;
103 let key = match key_ver {
104 KeyVersion::V2 | KeyVersion::V3 => private_key_parser_v2_v3(&key_ver, i)?,
105 KeyVersion::V4 | KeyVersion::V6 => private_key_parser_v4_v6(&key_ver, i)?,
106 KeyVersion::V5 | KeyVersion::Other(_) => {
107 unsupported_err!("key version {:?}", key_ver);
108 }
109 };
110 Ok(key)
111}