Skip to content

Commit 9ef6f5d

Browse files
authored
fix(rust/signed-doc): Preserve original raw_bytes (#345)
* add test * add raw_bytes field * fix spelling * wip * fix test * fix clippy
1 parent b9d9c4f commit 9ef6f5d

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

rust/signed_doc/src/builder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ impl Builder {
2626
metadata: Metadata::default(),
2727
content: Content::default(),
2828
signatures: Signatures::default(),
29+
raw_bytes: None,
2930
})
3031
}
3132

@@ -91,6 +92,7 @@ impl From<&CatalystSignedDocument> for Builder {
9192
content: value.inner.content.clone(),
9293
signatures: value.inner.signatures.clone(),
9394
report: value.inner.report.clone(),
95+
raw_bytes: None,
9496
})
9597
}
9698
}

rust/signed_doc/src/lib.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ struct InnerCatalystSignedDocument {
4141
/// A comprehensive problem report, which could include a decoding errors along with
4242
/// the other validation errors
4343
report: ProblemReport,
44+
45+
/// raw CBOR bytes of the `CatalystSignedDocument` object.
46+
/// It is important to keep them to have a consistency what comes from the decoding
47+
/// process, so we would return the same data again
48+
raw_bytes: Option<Vec<u8>>,
4449
}
4550

4651
/// Keep all the contents private.
@@ -187,21 +192,30 @@ impl InnerCatalystSignedDocument {
187192
/// # Errors
188193
/// Could fails if the `CatalystSignedDocument` object is not valid.
189194
fn as_cose_sign(&self) -> anyhow::Result<coset::CoseSign> {
190-
let protected_header =
191-
Header::try_from(&self.metadata).context("Failed to encode Document Metadata")?;
195+
if let Some(raw_bytes) = self.raw_bytes.clone() {
196+
let cose_sign = coset::CoseSign::from_tagged_slice(raw_bytes.as_slice())
197+
.or_else(|_| coset::CoseSign::from_slice(raw_bytes.as_slice()))
198+
.map_err(|e| {
199+
minicbor::decode::Error::message(format!("Invalid COSE Sign document: {e}"))
200+
})?;
201+
Ok(cose_sign)
202+
} else {
203+
let protected_header =
204+
Header::try_from(&self.metadata).context("Failed to encode Document Metadata")?;
192205

193-
let content = self
194-
.content
195-
.encoded_bytes(self.metadata.content_encoding())?;
206+
let content = self
207+
.content
208+
.encoded_bytes(self.metadata.content_encoding())?;
196209

197-
let mut builder = coset::CoseSignBuilder::new()
198-
.protected(protected_header)
199-
.payload(content);
210+
let mut builder = coset::CoseSignBuilder::new()
211+
.protected(protected_header)
212+
.payload(content);
200213

201-
for signature in self.signatures.cose_signatures() {
202-
builder = builder.add_signature(signature);
214+
for signature in self.signatures.cose_signatures() {
215+
builder = builder.add_signature(signature);
216+
}
217+
Ok(builder.build())
203218
}
204-
Ok(builder.build())
205219
}
206220
}
207221

@@ -237,6 +251,7 @@ impl Decode<'_, ()> for CatalystSignedDocument {
237251
content,
238252
signatures,
239253
report,
254+
raw_bytes: Some(cose_bytes.to_vec()),
240255
}
241256
.into())
242257
}
@@ -247,7 +262,6 @@ impl Encode<()> for CatalystSignedDocument {
247262
&self, e: &mut encode::Encoder<W>, _ctx: &mut (),
248263
) -> Result<(), encode::Error<W::Error>> {
249264
let cose_sign = self.as_cose_sign().map_err(encode::Error::message)?;
250-
251265
let cose_bytes = cose_sign.to_tagged_vec().map_err(|e| {
252266
minicbor::encode::Error::message(format!("Failed to encode COSE Sign document: {e}"))
253267
})?;

rust/signed_doc/tests/decoding.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Integration test for COSE decoding part.
22
3-
use catalyst_signed_doc::*;
3+
use catalyst_signed_doc::{providers::tests::TestVerifyingKeyProvider, *};
44
use catalyst_types::catalyst_id::role_index::RoleId;
55
use common::create_dummy_key_pair;
66
use coset::TaggedCborSerializable;
@@ -56,9 +56,13 @@ fn catalyst_signed_doc_cbor_roundtrip_kid_as_id_test() {
5656
assert!(doc.problem_report().is_problematic());
5757
}
5858

59-
#[test]
60-
fn catalyst_signed_doc_parameters_aliases_test() {
59+
#[tokio::test]
60+
#[allow(clippy::too_many_lines)]
61+
async fn catalyst_signed_doc_parameters_aliases_test() {
6162
let (_, _, metadata_fields) = common::test_metadata();
63+
let (sk, pk, kid) = common::create_dummy_key_pair(RoleId::Role0).unwrap();
64+
let mut provider = TestVerifyingKeyProvider::default();
65+
provider.add_pk(kid.clone(), pk);
6266

6367
let content = serde_json::to_vec(&serde_json::Value::Null).unwrap();
6468

@@ -97,46 +101,58 @@ fn catalyst_signed_doc_parameters_aliases_test() {
97101
parameters_val_cbor.clone(),
98102
));
99103

100-
let doc: CatalystSignedDocument = cose_with_category_id
101-
.to_tagged_vec()
104+
let cbor_bytes = cose_with_category_id.to_tagged_vec().unwrap();
105+
let doc: CatalystSignedDocument = cbor_bytes.as_slice().try_into().unwrap();
106+
let doc = doc
107+
.into_builder()
108+
.add_signature(|m| sk.sign(&m).to_vec(), &kid)
102109
.unwrap()
103-
.as_slice()
104-
.try_into()
105-
.unwrap();
110+
.build();
106111
assert!(!doc.problem_report().is_problematic());
107112
assert!(doc.doc_meta().parameters().is_some());
113+
assert!(validator::validate_signatures(&doc, &provider)
114+
.await
115+
.unwrap());
108116

109117
// case: `brand_id`.
110-
let mut cose_with_category_id = cose.clone();
111-
cose_with_category_id.protected.header.rest.push((
118+
let mut cose_with_brand_id = cose.clone();
119+
cose_with_brand_id.protected.header.rest.push((
112120
coset::Label::Text("brand_id".to_string()),
113121
parameters_val_cbor.clone(),
114122
));
115123

116-
let doc: CatalystSignedDocument = cose_with_category_id
117-
.to_tagged_vec()
124+
let cbor_bytes = cose_with_brand_id.to_tagged_vec().unwrap();
125+
let doc: CatalystSignedDocument = cbor_bytes.as_slice().try_into().unwrap();
126+
let doc = doc
127+
.into_builder()
128+
.add_signature(|m| sk.sign(&m).to_vec(), &kid)
118129
.unwrap()
119-
.as_slice()
120-
.try_into()
121-
.unwrap();
130+
.build();
122131
assert!(!doc.problem_report().is_problematic());
123132
assert!(doc.doc_meta().parameters().is_some());
133+
assert!(validator::validate_signatures(&doc, &provider)
134+
.await
135+
.unwrap());
124136

125137
// case: `campaign_id`.
126-
let mut cose_with_category_id = cose.clone();
127-
cose_with_category_id.protected.header.rest.push((
138+
let mut cose_with_campaign_id = cose.clone();
139+
cose_with_campaign_id.protected.header.rest.push((
128140
coset::Label::Text("campaign_id".to_string()),
129141
parameters_val_cbor.clone(),
130142
));
131143

132-
let doc: CatalystSignedDocument = cose_with_category_id
133-
.to_tagged_vec()
144+
let cbor_bytes = cose_with_campaign_id.to_tagged_vec().unwrap();
145+
let doc: CatalystSignedDocument = cbor_bytes.as_slice().try_into().unwrap();
146+
let doc = doc
147+
.into_builder()
148+
.add_signature(|m| sk.sign(&m).to_vec(), &kid)
134149
.unwrap()
135-
.as_slice()
136-
.try_into()
137-
.unwrap();
150+
.build();
138151
assert!(!doc.problem_report().is_problematic());
139152
assert!(doc.doc_meta().parameters().is_some());
153+
assert!(validator::validate_signatures(&doc, &provider)
154+
.await
155+
.unwrap());
140156

141157
// `parameters` value along with its aliases are not allowed to be present at the
142158
let mut cose_with_category_id = cose.clone();

0 commit comments

Comments
 (0)