1use crate::{oids, AlgorithmIdentifier, AlgorithmIdentifierParameters};
2use oid::ObjectIdentifier;
3use picky_asn1::{
4 bit_string::BitString,
5 wrapper::{BitStringAsn1, BitStringAsn1Container, IntegerAsn1, OctetStringAsn1},
6};
7use serde::{de, ser, Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Debug, PartialEq, Eq, Clone)]
11pub enum PublicKey {
12 Rsa(EncapsulatedRsaPublicKey),
13 Ec(EncapsulatedEcPoint),
14 Ed(EncapsulatedEcPoint),
16}
17
18#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
19pub struct RsaPublicKey {
20 pub modulus: IntegerAsn1, pub public_exponent: IntegerAsn1, }
23
24pub type EncapsulatedRsaPublicKey = BitStringAsn1Container<RsaPublicKey>;
25
26pub type EcPoint = OctetStringAsn1;
27
28pub type EncapsulatedEcPoint = BitStringAsn1;
29
30#[derive(Debug, PartialEq, Eq, Clone)]
31pub struct SubjectPublicKeyInfo {
32 pub algorithm: AlgorithmIdentifier,
33 pub subject_public_key: PublicKey,
34}
35
36impl SubjectPublicKeyInfo {
37 pub fn new_rsa_key(modulus: IntegerAsn1, public_exponent: IntegerAsn1) -> Self {
38 Self {
39 algorithm: AlgorithmIdentifier::new_rsa_encryption(),
40 subject_public_key: PublicKey::Rsa(
41 RsaPublicKey {
42 modulus,
43 public_exponent,
44 }
45 .into(),
46 ),
47 }
48 }
49
50 pub fn new_ec_key(curve: ObjectIdentifier, point: BitString) -> Self {
51 Self {
52 algorithm: AlgorithmIdentifier::new_elliptic_curve(curve.into()),
53 subject_public_key: PublicKey::Ec(point.into()),
54 }
55 }
56
57 pub fn new_ed_key(curve: ObjectIdentifier, point: BitString) -> Self {
58 Self {
59 algorithm: AlgorithmIdentifier::new_unchecked(curve, AlgorithmIdentifierParameters::None),
60 subject_public_key: PublicKey::Ed(point.into()),
61 }
62 }
63}
64
65impl ser::Serialize for SubjectPublicKeyInfo {
66 fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
67 where
68 S: ser::Serializer,
69 {
70 use ser::SerializeSeq;
71
72 let mut seq = serializer.serialize_seq(Some(2))?;
73 seq.serialize_element(&self.algorithm)?;
74
75 match &self.subject_public_key {
76 PublicKey::Rsa(key) => seq.serialize_element(key)?,
77 PublicKey::Ec(key) => seq.serialize_element(key)?,
78 PublicKey::Ed(key) => seq.serialize_element(key)?,
79 }
80
81 seq.end()
82 }
83}
84
85impl<'de> de::Deserialize<'de> for SubjectPublicKeyInfo {
86 fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
87 where
88 D: de::Deserializer<'de>,
89 {
90 struct Visitor;
91
92 impl<'de> de::Visitor<'de> for Visitor {
93 type Value = SubjectPublicKeyInfo;
94
95 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
96 formatter.write_str("a valid DER-encoded subject public key info")
97 }
98
99 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
100 where
101 A: de::SeqAccess<'de>,
102 {
103 let algorithm: AlgorithmIdentifier = seq_next_element!(seq, AlgorithmIdentifier, "algorithm oid");
104
105 let subject_public_key = match Into::<String>::into(algorithm.oid()).as_str() {
106 oids::RSA_ENCRYPTION => PublicKey::Rsa(seq_next_element!(seq, SubjectPublicKeyInfo, "rsa key")),
107 oids::EC_PUBLIC_KEY => {
108 PublicKey::Ec(seq_next_element!(seq, SubjectPublicKeyInfo, "elliptic curves key"))
109 }
110 oids::ED25519 | oids::X25519 => {
111 PublicKey::Ed(seq_next_element!(seq, SubjectPublicKeyInfo, "curve25519 key"))
112 }
113 oids::ED448 | oids::X448 => {
114 PublicKey::Ed(seq_next_element!(seq, SubjectPublicKeyInfo, "curve448 key"))
115 }
116 _ => {
117 return Err(serde_invalid_value!(
118 SubjectPublicKeyInfo,
119 "unsupported algorithm (unknown oid)",
120 "a supported algorithm"
121 ));
122 }
123 };
124
125 Ok(SubjectPublicKeyInfo {
126 algorithm,
127 subject_public_key,
128 })
129 }
130 }
131
132 deserializer.deserialize_seq(Visitor)
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use base64::{engine::general_purpose, Engine as _};
140 use num_bigint_dig::BigInt;
141
142 #[test]
143 fn rsa_subject_public_key_info() {
144 let encoded = general_purpose::STANDARD
145 .decode(
146 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiLoIx\
147 mXaZAFRBKtHYZhiF8m+pYR+xGIpupvsdDEvKO92D6fIccgVLIW6p6sSNk\
148 oXx5J6KDSMbA/chy5M6pRvJkaCXCI4zlCPMYvPhI8OxN3RYPfdQTLpgPy\
149 wrlfdn2CAum7o4D8nR4NJacB3NfPnS9tsJ2L3p5iHviuTB4xm03IKmPPq\
150 saJy+nXUFC1XS9E/PseVHRuNvKa7WmlwSZngQzKAVSIwqpgCc+oP1pKEe\
151 J0M3LHFo8ao5SuzhfXUIGrPnkUKEE3m7B0b8xXZfP1N6ELoonWDK+RMgY\
152 IBaZdgBhPfHxF8KfTHvSzcUzWZojuR+ynaFL9AJK+8RiXnB4CJwIDAQAB",
153 )
154 .expect("invalid base64");
155
156 let algorithm = AlgorithmIdentifier::new_rsa_encryption();
159 check_serde!(algorithm: AlgorithmIdentifier in encoded[4..19]);
160
161 let modulus = IntegerAsn1::from_bytes_be_signed(vec![
164 0x00, 0xb2, 0x22, 0xe8, 0x23, 0x19, 0x97, 0x69, 0x90, 0x5, 0x44, 0x12, 0xad, 0x1d, 0x86, 0x61, 0x88, 0x5f,
165 0x26, 0xfa, 0x96, 0x11, 0xfb, 0x11, 0x88, 0xa6, 0xea, 0x6f, 0xb1, 0xd0, 0xc4, 0xbc, 0xa3, 0xbd, 0xd8, 0x3e,
166 0x9f, 0x21, 0xc7, 0x20, 0x54, 0xb2, 0x16, 0xea, 0x9e, 0xac, 0x48, 0xd9, 0x28, 0x5f, 0x1e, 0x49, 0xe8, 0xa0,
167 0xd2, 0x31, 0xb0, 0x3f, 0x72, 0x1c, 0xb9, 0x33, 0xaa, 0x51, 0xbc, 0x99, 0x1a, 0x9, 0x70, 0x88, 0xe3, 0x39,
168 0x42, 0x3c, 0xc6, 0x2f, 0x3e, 0x12, 0x3c, 0x3b, 0x13, 0x77, 0x45, 0x83, 0xdf, 0x75, 0x4, 0xcb, 0xa6, 0x3,
169 0xf2, 0xc2, 0xb9, 0x5f, 0x76, 0x7d, 0x82, 0x2, 0xe9, 0xbb, 0xa3, 0x80, 0xfc, 0x9d, 0x1e, 0xd, 0x25, 0xa7,
170 0x1, 0xdc, 0xd7, 0xcf, 0x9d, 0x2f, 0x6d, 0xb0, 0x9d, 0x8b, 0xde, 0x9e, 0x62, 0x1e, 0xf8, 0xae, 0x4c, 0x1e,
171 0x31, 0x9b, 0x4d, 0xc8, 0x2a, 0x63, 0xcf, 0xaa, 0xc6, 0x89, 0xcb, 0xe9, 0xd7, 0x50, 0x50, 0xb5, 0x5d, 0x2f,
172 0x44, 0xfc, 0xfb, 0x1e, 0x54, 0x74, 0x6e, 0x36, 0xf2, 0x9a, 0xed, 0x69, 0xa5, 0xc1, 0x26, 0x67, 0x81, 0xc,
173 0xca, 0x1, 0x54, 0x88, 0xc2, 0xaa, 0x60, 0x9, 0xcf, 0xa8, 0x3f, 0x5a, 0x4a, 0x11, 0xe2, 0x74, 0x33, 0x72,
174 0xc7, 0x16, 0x8f, 0x1a, 0xa3, 0x94, 0xae, 0xce, 0x17, 0xd7, 0x50, 0x81, 0xab, 0x3e, 0x79, 0x14, 0x28, 0x41,
175 0x37, 0x9b, 0xb0, 0x74, 0x6f, 0xcc, 0x57, 0x65, 0xf3, 0xf5, 0x37, 0xa1, 0xb, 0xa2, 0x89, 0xd6, 0xc, 0xaf,
176 0x91, 0x32, 0x6, 0x8, 0x5, 0xa6, 0x5d, 0x80, 0x18, 0x4f, 0x7c, 0x7c, 0x45, 0xf0, 0xa7, 0xd3, 0x1e, 0xf4,
177 0xb3, 0x71, 0x4c, 0xd6, 0x66, 0x88, 0xee, 0x47, 0xec, 0xa7, 0x68, 0x52, 0xfd, 0x0, 0x92, 0xbe, 0xf1, 0x18,
178 0x97, 0x9c, 0x1e, 0x2, 0x27,
179 ]);
180 check_serde!(modulus: IntegerAsn1 in encoded[28..289]);
181
182 let public_exponent: IntegerAsn1 = BigInt::from(65537).to_signed_bytes_be().into();
183 check_serde!(public_exponent: IntegerAsn1 in encoded[289..294]);
184
185 let subject_public_key: EncapsulatedRsaPublicKey = RsaPublicKey {
188 modulus,
189 public_exponent,
190 }
191 .into();
192 check_serde!(subject_public_key: EncapsulatedRsaPublicKey in encoded[19..294]);
193
194 let info = SubjectPublicKeyInfo {
197 algorithm,
198 subject_public_key: PublicKey::Rsa(subject_public_key),
199 };
200 check_serde!(info: SubjectPublicKeyInfo in encoded);
201 }
202}