Skip to content

Commit 44efc78

Browse files
committed
add cbor roundtrip test
1 parent 5f14e50 commit 44efc78

File tree

6 files changed

+71
-58
lines changed

6 files changed

+71
-58
lines changed

rust/signed_doc/src/lib.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Display for CatalystSignedDocument {
4545
writeln!(f, "{}", self.inner.metadata)?;
4646
writeln!(f, "Payload Size: {} bytes", self.inner.content.len())?;
4747
writeln!(f, "Signature Information")?;
48-
if self.inner.signatures.0.is_empty() {
48+
if self.inner.signatures.is_empty() {
4949
writeln!(f, " This document is unsigned.")?;
5050
} else {
5151
for kid in &self.inner.signatures.kids() {
@@ -177,7 +177,7 @@ impl Encode<()> for CatalystSignedDocument {
177177
.protected(protected_header)
178178
.payload(self.inner.content.bytes().to_vec());
179179

180-
for signature in self.signatures().signatures() {
180+
for signature in self.signatures().cose_signatures() {
181181
builder = builder.add_signature(signature);
182182
}
183183

@@ -192,3 +192,54 @@ impl Encode<()> for CatalystSignedDocument {
192192
.map_err(|_| minicbor::encode::Error::message("Failed to encode to CBOR"))
193193
}
194194
}
195+
196+
#[cfg(test)]
197+
mod tests {
198+
use metadata::{ContentEncoding, ContentType};
199+
200+
use super::*;
201+
202+
#[test]
203+
fn catalyst_signed_doc_cbor_roundtrip_test() {
204+
let uuid_v7 = UuidV7::new();
205+
let uuid_v4 = UuidV4::new();
206+
let section = "some section".to_string();
207+
let collabs = vec!["collab1".to_string(), "collab2".to_string()];
208+
let content_type = ContentType::Json;
209+
let content_encoding = ContentEncoding::Brotli;
210+
211+
let metadata = serde_json::from_value(serde_json::json!({
212+
"content-type": content_type.to_string(),
213+
"content-encoding": content_encoding.to_string(),
214+
"type": uuid_v4.to_string(),
215+
"id": uuid_v7.to_string(),
216+
"ver": uuid_v7.to_string(),
217+
"ref": {"id": uuid_v7.to_string()},
218+
"reply": {"id": uuid_v7.to_string(), "ver": uuid_v7.to_string()},
219+
"template": {"id": uuid_v7.to_string()},
220+
"section": section,
221+
"collabs": collabs,
222+
"campaign_id": uuid_v4.to_string(),
223+
"election_id": uuid_v4.to_string(),
224+
"brand_id": uuid_v4.to_string(),
225+
"category_id": uuid_v4.to_string(),
226+
}))
227+
.unwrap();
228+
let payload = vec![1, 2, 4, 5, 6, 7, 8, 9];
229+
let content = Content::new(payload, content_type, Some(content_encoding)).unwrap();
230+
231+
let doc = CatalystSignedDocument {
232+
inner: InnerCatalystSignedDocument {
233+
metadata,
234+
content,
235+
signatures: Signatures::new(),
236+
}
237+
.into(),
238+
};
239+
240+
let mut bytes = Vec::new();
241+
minicbor::encode_with(doc, &mut bytes, &mut ()).unwrap();
242+
let _decoded: CatalystSignedDocument =
243+
minicbor::decode_with(bytes.as_slice(), &mut ()).unwrap();
244+
}
245+
}

rust/signed_doc/src/metadata/algorithm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Cryptographic Algorithm in COSE SIGN protected header.
22
33
/// Cryptography Algorithm.
4-
#[derive(Copy, Clone, Debug, serde::Deserialize)]
4+
#[derive(Copy, Clone, Debug, PartialEq, serde::Deserialize)]
55
pub enum Algorithm {
66
/// `EdDSA`
77
EdDSA,

rust/signed_doc/src/metadata/document_ref.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use coset::cbor::Value;
44
use super::{decode_cbor_uuid, encode_cbor_uuid, UuidV7};
55

66
/// Reference to a Document.
7-
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)]
7+
#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
88
#[serde(untagged)]
99
pub enum DocumentRef {
1010
/// Reference to the latest document

rust/signed_doc/src/metadata/extra_fields.rs

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const CATEGORY_ID_KEY: &str = "category_id";
2727
/// Extra Metadata Fields.
2828
///
2929
/// These values are extracted from the COSE Sign protected header labels.
30-
#[derive(Clone, Default, Debug, serde::Serialize, serde::Deserialize)]
30+
#[derive(Clone, Default, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
3131
pub struct ExtraFields {
3232
/// Reference to the latest document.
3333
#[serde(rename = "ref", skip_serializing_if = "Option::is_none")]
@@ -271,50 +271,13 @@ impl TryFrom<&ProtectedHeader> for ExtraFields {
271271

272272
#[cfg(test)]
273273
mod tests {
274-
use catalyst_types::uuid::{V4, V7};
275-
276274
use super::*;
277275

278276
#[test]
279-
fn extra_fields_json_serde_test() {
277+
fn empty_extra_fields_json_serde_test() {
280278
let extra = ExtraFields::default();
281279

282280
let json = serde_json::to_value(extra).unwrap();
283281
assert_eq!(json, serde_json::json!({}));
284-
285-
let uuid_v7 = V7::new();
286-
let uuid_v4 = V4::new();
287-
let section = "some section".to_string();
288-
let collabs = vec!["collab1".to_string(), "collab2".to_string()];
289-
let extra = ExtraFields {
290-
doc_ref: Some(DocumentRef::Latest { id: uuid_v7 }),
291-
reply: Some(DocumentRef::WithVer {
292-
id: uuid_v7,
293-
ver: uuid_v7,
294-
}),
295-
template: Some(DocumentRef::Latest { id: uuid_v7 }),
296-
section: Some(section.clone()),
297-
collabs: collabs.clone(),
298-
campaign_id: Some(uuid_v4),
299-
election_id: Some(uuid_v4),
300-
brand_id: Some(uuid_v4),
301-
category_id: Some(uuid_v4),
302-
};
303-
304-
let json = serde_json::to_value(extra).unwrap();
305-
assert_eq!(
306-
json,
307-
serde_json::json!({
308-
"ref": {"id": uuid_v7.to_string()},
309-
"reply": {"id": uuid_v7.to_string(), "ver": uuid_v7.to_string()},
310-
"template": {"id": uuid_v7.to_string()},
311-
"section": section,
312-
"collabs": collabs,
313-
"campaign_id": uuid_v4.to_string(),
314-
"election_id": uuid_v4.to_string(),
315-
"brand_id": uuid_v4.to_string(),
316-
"category_id": uuid_v4.to_string(),
317-
})
318-
);
319282
}
320283
}

rust/signed_doc/src/metadata/mod.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,18 @@ const VER_KEY: &str = "ver";
3434
/// Document Metadata.
3535
///
3636
/// These values are extracted from the COSE Sign protected header.
37-
#[derive(Clone, Debug, serde::Deserialize)]
37+
#[derive(Clone, Debug, PartialEq, serde::Deserialize)]
3838
pub struct Metadata {
39+
/// Cryptographic Algorithm
40+
#[serde(default = "Algorithm::default")]
41+
alg: Algorithm,
3942
/// Document Type `UUIDv4`.
4043
#[serde(rename = "type")]
4144
doc_type: DocumentType,
4245
/// Document ID `UUIDv7`.
4346
id: DocumentId,
4447
/// Document Version `UUIDv7`.
4548
ver: DocumentVersion,
46-
/// Cryptographic Algorithm
47-
alg: Algorithm,
4849
/// Document Payload Content Type.
4950
#[serde(rename = "content-type")]
5051
content_type: ContentType,
@@ -75,12 +76,6 @@ impl Metadata {
7576
self.ver.into()
7677
}
7778

78-
/// Return Cryptography Algorithm.
79-
#[must_use]
80-
pub fn algorithm(&self) -> coset::iana::Algorithm {
81-
self.alg.into()
82-
}
83-
8479
/// Returns the Document Content Type, if any.
8580
#[must_use]
8681
pub fn content_type(&self) -> ContentType {
@@ -154,9 +149,7 @@ impl TryFrom<&coset::ProtectedHeader> for Metadata {
154149
Err(e) => errors.push(anyhow!("Invalid Document Algorithm: {e}")),
155150
}
156151
} else {
157-
errors.push(anyhow!(
158-
"Invalid COSE protected header, missing Content-Type field"
159-
));
152+
errors.push(anyhow!("Invalid COSE protected header, missing alg field"));
160153
}
161154

162155
let mut content_type = None;

rust/signed_doc/src/signature/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@ pub struct Signature {
1313
}
1414

1515
/// List of Signatures.
16-
#[derive(Debug, Clone)]
17-
pub struct Signatures(pub(crate) Vec<Signature>);
16+
#[derive(Debug, Clone, Default)]
17+
pub struct Signatures(Vec<Signature>);
1818

1919
impl Signatures {
20+
/// Creates an empty signatures list.
21+
#[must_use]
22+
pub fn new() -> Self {
23+
Self(Vec::new())
24+
}
25+
2026
/// List of signature Key IDs.
2127
#[must_use]
2228
pub fn kids(&self) -> Vec<KidUri> {
@@ -25,7 +31,7 @@ impl Signatures {
2531

2632
/// List of signatures.
2733
#[must_use]
28-
pub fn signatures(&self) -> Vec<CoseSignature> {
34+
pub fn cose_signatures(&self) -> Vec<CoseSignature> {
2935
self.0.iter().map(|sig| sig.signature.clone()).collect()
3036
}
3137

0 commit comments

Comments
 (0)