@@ -17,7 +17,7 @@ pub use builder::Builder;
1717use catalyst_types:: problem_report:: ProblemReport ;
1818pub use content:: Content ;
1919use coset:: { CborSerializable , Header } ;
20- use ed25519_dalek:: VerifyingKey ;
20+ use ed25519_dalek:: { ed25519 :: signature :: Signer , SecretKey , VerifyingKey } ;
2121use error:: CatalystSignedDocError ;
2222pub use metadata:: { DocumentRef , ExtraFields , Metadata , UuidV4 , UuidV7 } ;
2323pub 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 ( ) ;
0 commit comments