Skip to content

Commit c303489

Browse files
committed
Merge branch 'main' into feat/cat-sign-doc-validator
2 parents 9c40793 + 85d3e41 commit c303489

File tree

5 files changed

+62
-21
lines changed

5 files changed

+62
-21
lines changed

rust/catalyst-types/src/uuid/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! `UUID` types.
22
3+
pub use uuid::Uuid;
34
#[allow(clippy::module_name_repetitions)]
45
pub use uuid_v4::UuidV4;
56
#[allow(clippy::module_name_repetitions)]

rust/signed_doc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ clap = { version = "4.5.23", features = ["derive", "env"] }
2626

2727

2828
[dev-dependencies]
29+
base64-url = "3.0.0"
2930
rand = "0.8.5"
3031

3132

rust/signed_doc/src/lib.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,15 @@ impl Encode<()> for CatalystSignedDocument {
324324

325325
#[cfg(test)]
326326
mod tests {
327+
use std::str::FromStr;
328+
329+
use ed25519_dalek::SigningKey;
327330
use metadata::{ContentEncoding, ContentType};
331+
use rand::rngs::OsRng;
328332

329333
use super::*;
330334

331-
#[test]
332-
fn catalyst_signed_doc_cbor_roundtrip_test() {
335+
fn test_metadata() -> anyhow::Result<(UuidV7, UuidV4, Metadata)> {
333336
let uuid_v7 = UuidV7::new();
334337
let uuid_v4 = UuidV4::new();
335338
let section = "some section".to_string();
@@ -353,7 +356,13 @@ mod tests {
353356
"brand_id": {"id": uuid_v7.to_string()},
354357
"category_id": {"id": uuid_v7.to_string()},
355358
}))
356-
.unwrap();
359+
.map_err(|_| anyhow::anyhow!("Invalid example metadata. This should not happen."))?;
360+
Ok((uuid_v7, uuid_v4, metadata))
361+
}
362+
363+
#[test]
364+
fn catalyst_signed_doc_cbor_roundtrip_test() {
365+
let (uuid_v7, uuid_v4, metadata) = test_metadata().unwrap();
357366
let content = serde_json::to_vec(&serde_json::Value::Null).unwrap();
358367

359368
let doc = Builder::new()
@@ -371,4 +380,37 @@ mod tests {
371380
assert_eq!(decoded.doc_content().decoded_bytes(), &content);
372381
assert_eq!(decoded.doc_meta(), metadata.extra());
373382
}
383+
384+
#[test]
385+
fn signature_verification_test() {
386+
let mut csprng = OsRng;
387+
let sk: SigningKey = SigningKey::generate(&mut csprng);
388+
let content = serde_json::to_vec(&serde_json::Value::Null).unwrap();
389+
let pk = sk.verifying_key();
390+
391+
let kid_str = format!(
392+
"kid.catalyst-rbac://cardano/{}/0/0",
393+
base64_url::encode(pk.as_bytes())
394+
);
395+
396+
let kid = KidUri::from_str(&kid_str).unwrap();
397+
let (_, _, metadata) = test_metadata().unwrap();
398+
let signed_doc = Builder::new()
399+
.with_decoded_content(content)
400+
.with_metadata(metadata)
401+
.add_signature(sk.to_bytes(), kid.clone())
402+
.unwrap()
403+
.build()
404+
.unwrap();
405+
406+
assert!(signed_doc
407+
.verify(|k| {
408+
if k.to_string() == kid.to_string() {
409+
pk
410+
} else {
411+
k.role0_pk()
412+
}
413+
})
414+
.is_ok());
415+
}
374416
}

rust/signed_doc/src/metadata/extra_fields.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Catalyst Signed Document Extra Fields.
22
3-
use anyhow::bail;
43
use catalyst_types::{problem_report::ProblemReport, uuid::UuidV4};
54
use coset::{cbor::Value, Label, ProtectedHeader};
65

@@ -160,12 +159,14 @@ impl ExtraFields {
160159
}
161160

162161
/// Converting COSE Protected Header to `ExtraFields`.
162+
/// Return `None` if it fails during
163163
#[allow(clippy::too_many_lines)]
164164
pub(crate) fn from_protected_header(
165165
protected: &ProtectedHeader, error_report: &ProblemReport,
166-
) -> anyhow::Result<Self> {
166+
) -> Option<Self> {
167167
/// Context for error messages.
168168
const CONTEXT: &str = "COSE ProtectedHeader to ExtraFields";
169+
let mut valid = true;
169170

170171
let mut extra = ExtraFields::default();
171172

@@ -177,6 +178,7 @@ impl ExtraFields {
177178
extra.doc_ref = Some(doc_ref);
178179
},
179180
Err(e) => {
181+
valid = false;
180182
error_report.conversion_error(
181183
"CBOR COSE protected header doc ref",
182184
&format!("{cbor_doc_ref:?}"),
@@ -195,6 +197,7 @@ impl ExtraFields {
195197
extra.template = Some(doc_template);
196198
},
197199
Err(e) => {
200+
valid = false;
198201
error_report.conversion_error(
199202
"CBOR COSE protected header document template",
200203
&format!("{cbor_doc_template:?}"),
@@ -213,6 +216,7 @@ impl ExtraFields {
213216
extra.reply = Some(doc_reply);
214217
},
215218
Err(e) => {
219+
valid = false;
216220
error_report.conversion_error(
217221
"CBOR COSE protected header document reply",
218222
&format!("{cbor_doc_reply:?}"),
@@ -231,6 +235,7 @@ impl ExtraFields {
231235
extra.section = Some(doc_section);
232236
},
233237
Err(e) => {
238+
valid = false;
234239
error_report.conversion_error(
235240
"COSE protected header document section",
236241
&format!("{cbor_doc_section:?}"),
@@ -253,6 +258,7 @@ impl ExtraFields {
253258
c.push(collaborator);
254259
},
255260
Err(e) => {
261+
valid = false;
256262
error_report.conversion_error(
257263
&format!("COSE protected header collaborator index {ids}"),
258264
&format!("{collaborator:?}"),
@@ -265,6 +271,7 @@ impl ExtraFields {
265271
extra.collabs = c;
266272
},
267273
Err(e) => {
274+
valid = false;
268275
error_report.conversion_error(
269276
"CBOR COSE protected header collaborators",
270277
&format!("{cbor_doc_collabs:?}"),
@@ -283,6 +290,7 @@ impl ExtraFields {
283290
extra.brand_id = Some(brand_id);
284291
},
285292
Err(e) => {
293+
valid = false;
286294
error_report.conversion_error(
287295
"CBOR COSE protected header brand ID",
288296
&format!("{cbor_doc_brand_id:?}"),
@@ -301,6 +309,7 @@ impl ExtraFields {
301309
extra.campaign_id = Some(campaign_id);
302310
},
303311
Err(e) => {
312+
valid = false;
304313
error_report.conversion_error(
305314
"CBOR COSE protected header campaign ID",
306315
&format!("{cbor_doc_campaign_id:?}"),
@@ -319,6 +328,7 @@ impl ExtraFields {
319328
extra.election_id = Some(election_id);
320329
},
321330
Err(e) => {
331+
valid = false;
322332
error_report.conversion_error(
323333
"CBOR COSE protected header election ID",
324334
&format!("{cbor_doc_election_id:?}"),
@@ -337,6 +347,7 @@ impl ExtraFields {
337347
extra.category_id = Some(category_id);
338348
},
339349
Err(e) => {
350+
valid = false;
340351
error_report.conversion_error(
341352
"CBOR COSE protected header category ID",
342353
&format!("{cbor_doc_category_id:?}"),
@@ -347,10 +358,7 @@ impl ExtraFields {
347358
}
348359
}
349360

350-
if error_report.is_problematic() {
351-
bail!("Failed to convert COSE ProtectedHeader to ExtraFields");
352-
}
353-
Ok(extra)
361+
valid.then_some(extra)
354362
}
355363
}
356364

rust/signed_doc/src/metadata/mod.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -217,18 +217,7 @@ impl Metadata {
217217
error_report.missing_field("ver", "Missing ver field in COSE protected header");
218218
}
219219

220-
let extra = ExtraFields::from_protected_header(protected, error_report).map_or_else(
221-
|e| {
222-
error_report.conversion_error(
223-
"COSE protected header",
224-
&format!("{protected:?}"),
225-
&format!("Expected ExtraField: {e}"),
226-
&format!("{CONTEXT}, ExtraFields"),
227-
);
228-
None
229-
},
230-
Some,
231-
);
220+
let extra = ExtraFields::from_protected_header(protected, error_report);
232221

233222
match (content_type, content_encoding, id, doc_type, ver, extra) {
234223
(

0 commit comments

Comments
 (0)