Skip to content

Commit 22c46f0

Browse files
committed
feat(rust/signed-doc): add signatures to Catalyst Signed Document
1 parent dd60045 commit 22c46f0

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

rust/signed_doc/src/lib.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use builder::Builder;
1717
use catalyst_types::problem_report::ProblemReport;
1818
pub use content::Content;
1919
use coset::{CborSerializable, Header};
20-
use ed25519_dalek::VerifyingKey;
20+
use ed25519_dalek::{ed25519::signature::Signer, SecretKey, VerifyingKey};
2121
use error::CatalystSignedDocError;
2222
pub use metadata::{DocumentRef, ExtraFields, Metadata, UuidV4, UuidV7};
2323
pub use minicbor::{decode, encode, Decode, Decoder, Encode};
@@ -259,6 +259,44 @@ impl CatalystSignedDocument {
259259
Ok(())
260260
}
261261

262+
/// Add a signature to the Catalyst Signed Document.
263+
///
264+
/// # Returns
265+
///
266+
/// A new Catalyst Signed Document with the added signature.
267+
///
268+
/// # Errors
269+
///
270+
/// Fails if the current signed document cannot be encoded as COSE SIGN,
271+
/// or if the Arc inner value cannot be obtained.
272+
pub fn sign(self, sk: SecretKey, kid: KidUri) -> anyhow::Result<Self> {
273+
let cose_sign = self.as_cose_sign()?;
274+
let Some(InnerCatalystSignedDocument {
275+
metadata,
276+
content,
277+
mut signatures,
278+
}) = Arc::into_inner(self.inner)
279+
else {
280+
anyhow::bail!("Failed to extract inner signed document");
281+
};
282+
let sk = ed25519_dalek::SigningKey::from_bytes(&sk);
283+
let protected_header = coset::HeaderBuilder::new()
284+
.key_id(kid.to_string().into_bytes())
285+
.algorithm(metadata.algorithm().into());
286+
let mut signature = coset::CoseSignatureBuilder::new()
287+
.protected(protected_header.build())
288+
.build();
289+
let data_to_sign = cose_sign.tbs_data(&[], &signature);
290+
signature.signature = sk.sign(&data_to_sign).to_vec();
291+
signatures.push(kid, signature);
292+
Ok(InnerCatalystSignedDocument {
293+
metadata,
294+
content,
295+
signatures,
296+
}
297+
.into())
298+
}
299+
262300
/// Convert Catalyst Signed Document into `coset::CoseSign`
263301
fn as_cose_sign(&self) -> anyhow::Result<coset::CoseSign> {
264302
let mut cose_bytes: Vec<u8> = Vec::new();

rust/signed_doc/src/metadata/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ pub struct Metadata {
5959
}
6060

6161
impl Metadata {
62+
/// Return Document Cryptographic Algorithm
63+
#[must_use]
64+
pub fn algorithm(&self) -> Algorithm {
65+
self.alg
66+
}
67+
6268
/// Return Document Type `UUIDv4`.
6369
#[must_use]
6470
pub fn doc_type(&self) -> UuidV4 {

rust/signed_doc/src/signature/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ impl Signatures {
3737
self.0.iter().map(|sig| sig.signature.clone()).collect()
3838
}
3939

40+
/// Add a new signature
41+
pub fn push(&mut self, kid: KidUri, signature: CoseSignature) {
42+
self.0.push(Signature { kid, signature });
43+
}
44+
4045
/// Number of signatures.
4146
#[must_use]
4247
pub fn len(&self) -> usize {

0 commit comments

Comments
 (0)