confium_pki/cms/
signed_data.rs1use chrono::{DateTime, Utc};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct SignedData {
14 pub version: u32,
16 pub digest_algorithms: Vec<AlgorithmIdentifier>,
18 pub encap_content_info: EncapContentInfo,
20 pub certificates: Vec<Vec<u8>>,
22 pub signer_infos: Vec<SignerInfo>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct EncapContentInfo {
29 pub content_type: String,
31 #[serde(default)]
33 pub content: Option<Vec<u8>>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct AlgorithmIdentifier {
39 pub oid: String,
41 #[serde(default)]
43 pub parameters: Option<Vec<u8>>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct SignerInfo {
49 pub version: u32,
51 pub sid: SignerIdentifier,
53 pub digest_algorithm: AlgorithmIdentifier,
55 #[serde(default)]
57 pub signed_attrs: Vec<Attribute>,
58 pub signature_algorithm: AlgorithmIdentifier,
60 pub signature: Vec<u8>,
62 #[serde(default)]
64 pub unsigned_attrs: Vec<Attribute>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(tag = "kind", rename_all = "snake_case")]
70pub enum SignerIdentifier {
71 IssuerAndSerialNumber {
73 issuer_der: Vec<u8>,
75 serial_number: Vec<u8>,
77 },
78 SubjectKeyIdentifier {
80 key_identifier: Vec<u8>,
82 },
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct Attribute {
88 pub oid: String,
90 pub values: Vec<Vec<u8>>,
92}
93
94impl SignedData {
95 pub fn new(content_type: impl Into<String>, content: Option<Vec<u8>>) -> Self {
97 Self {
98 version: 1,
99 digest_algorithms: Vec::new(),
100 encap_content_info: EncapContentInfo {
101 content_type: content_type.into(),
102 content,
103 },
104 certificates: Vec::new(),
105 signer_infos: Vec::new(),
106 }
107 }
108
109 pub fn add_signer(&mut self, signer_info: SignerInfo) {
111 let oid = &signer_info.digest_algorithm.oid;
113 if !self.digest_algorithms.iter().any(|a| &a.oid == oid) {
114 self.digest_algorithms
115 .push(signer_info.digest_algorithm.clone());
116 }
117 self.signer_infos.push(signer_info);
118 }
119
120 pub fn add_certificate(&mut self, cert_der: Vec<u8>) {
122 self.certificates.push(cert_der);
123 }
124
125 pub fn signer_count(&self) -> usize {
127 self.signer_infos.len()
128 }
129
130 pub fn signing_time(&self) -> Option<DateTime<Utc>> {
132 self.signer_infos.first().and_then(|s| {
133 s.signed_attrs.iter().find_map(|a| {
134 if a.oid == "1.2.840.113549.1.9.5" {
135 None
138 } else {
139 None
140 }
141 })
142 })
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn signed_data_construction() {
152 let mut sd = SignedData::new("1.2.840.113549.1.7.1", Some(b"hello".to_vec()));
153 let signer = SignerInfo {
154 version: 1,
155 sid: SignerIdentifier::SubjectKeyIdentifier {
156 key_identifier: vec![1, 2, 3],
157 },
158 digest_algorithm: AlgorithmIdentifier {
159 oid: "2.16.840.1.101.3.4.2.1".into(), parameters: None,
161 },
162 signed_attrs: Vec::new(),
163 signature_algorithm: AlgorithmIdentifier {
164 oid: "1.2.840.113549.1.1.11".into(), parameters: None,
166 },
167 signature: vec![0u8; 256],
168 unsigned_attrs: Vec::new(),
169 };
170 sd.add_signer(signer);
171 sd.add_certificate(vec![0u8; 100]);
172 assert_eq!(sd.signer_count(), 1);
173 assert_eq!(sd.digest_algorithms.len(), 1);
174 assert_eq!(sd.certificates.len(), 1);
175 }
176}