bc_components/symmetric/
encrypted_message.rs1use std::borrow::Cow;
2use bc_ur::prelude::*;
3use crate::{ Nonce, Digest, DigestProvider, tags, AuthenticationTag };
4
5#[derive(Clone, Eq, PartialEq)]
30pub struct EncryptedMessage {
31 ciphertext: Vec<u8>,
32 aad: Vec<u8>, nonce: Nonce,
34 auth: AuthenticationTag,
35}
36
37impl EncryptedMessage {
38 pub fn new(
42 ciphertext: impl Into<Vec<u8>>,
43 aad: impl Into<Vec<u8>>,
44 nonce: Nonce,
45 auth: AuthenticationTag
46 ) -> Self {
47 Self {
48 ciphertext: ciphertext.into(),
49 aad: aad.into(),
50 nonce,
51 auth,
52 }
53 }
54
55 pub fn ciphertext(&self) -> &Vec<u8> {
57 &self.ciphertext
58 }
59
60 pub fn aad(&self) -> &Vec<u8> {
62 &self.aad
63 }
64
65 pub fn nonce(&self) -> &Nonce {
67 &self.nonce
68 }
69
70 pub fn authentication_tag(&self) -> &AuthenticationTag {
72 &self.auth
73 }
74
75 pub fn opt_digest(&self) -> Option<Digest> {
77 CBOR::try_from_data(self.aad())
78 .ok()
79 .and_then(|data| Digest::try_from(data).ok())
80 }
81
82 pub fn has_digest(&self) -> bool {
84 self.opt_digest().is_some()
85 }
86}
87
88impl std::fmt::Debug for EncryptedMessage {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 f.debug_struct("EncryptedMessage")
92 .field("ciphertext", &hex::encode(&self.ciphertext))
93 .field("aad", &hex::encode(&self.aad))
94 .field("nonce", &self.nonce)
95 .field("auth", &self.auth)
96 .finish()
97 }
98}
99
100impl AsRef<EncryptedMessage> for EncryptedMessage {
102 fn as_ref(&self) -> &EncryptedMessage {
103 self
104 }
105}
106
107impl DigestProvider for EncryptedMessage {
109 fn digest(&self) -> Cow<'_, Digest> {
110 let a = self.opt_digest().unwrap();
111 Cow::Owned(a)
112 }
113}
114
115impl CBORTagged for EncryptedMessage {
117 fn cbor_tags() -> Vec<Tag> {
118 tags_for_values(&[tags::TAG_ENCRYPTED])
119 }
120}
121
122impl From<EncryptedMessage> for CBOR {
124 fn from(value: EncryptedMessage) -> Self {
125 value.tagged_cbor()
126 }
127}
128
129impl TryFrom<CBOR> for EncryptedMessage {
131 type Error = dcbor::Error;
132
133 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
134 Self::from_tagged_cbor(cbor)
135 }
136}
137
138impl CBORTaggedEncodable for EncryptedMessage {
140 fn untagged_cbor(&self) -> CBOR {
141 let mut a = vec![
142 CBOR::to_byte_string(&self.ciphertext),
143 CBOR::to_byte_string(self.nonce.data()),
144 CBOR::to_byte_string(self.auth.data())
145 ];
146
147 if !self.aad.is_empty() {
148 a.push(CBOR::to_byte_string(&self.aad));
149 }
150
151 a.into()
152 }
153}
154
155impl CBORTaggedDecodable for EncryptedMessage {
157 fn from_untagged_cbor(cbor: CBOR) -> dcbor::Result<Self> {
158 match cbor.as_case() {
159 CBORCase::Array(elements) => {
160 if elements.len() < 3 {
161 return Err("EncryptedMessage must have at least 3 elements".into());
162 }
163 let ciphertext = CBOR::try_into_byte_string(elements[0].clone())?;
164 let nonce_data = CBOR::try_into_byte_string(elements[1].clone())?;
165 let nonce = Nonce::from_data_ref(nonce_data)?;
166 let auth_data = CBOR::try_into_byte_string(elements[2].clone())?;
167 let auth = AuthenticationTag::from_data_ref(auth_data)?;
168 let aad = if elements.len() > 3 {
169 CBOR::try_into_byte_string(elements[3].clone())?
170 } else {
171 Vec::new()
172 };
173 Ok(Self::new(ciphertext, aad, nonce, auth))
174 }
175 _ => return Err("EncryptedMessage must be an array".into()),
176 }
177 }
178}