@@ -12,6 +12,7 @@ pub mod validator;
1212use std:: {
1313 convert:: TryFrom ,
1414 fmt:: { Display , Formatter } ,
15+ future:: Future ,
1516 sync:: Arc ,
1617} ;
1718
@@ -20,11 +21,11 @@ use catalyst_types::problem_report::ProblemReport;
2021pub use catalyst_types:: uuid:: { Uuid , UuidV4 , UuidV7 } ;
2122pub use content:: Content ;
2223use coset:: { CborSerializable , Header } ;
24+ use ed25519_dalek:: VerifyingKey ;
2325use error:: CatalystSignedDocError ;
2426use metadata:: { ContentEncoding , ContentType } ;
2527pub use metadata:: { DocumentRef , ExtraFields , Metadata } ;
2628pub use minicbor:: { decode, encode, Decode , Decoder , Encode , Encoder } ;
27- pub use rbac_registration:: cardano:: cip509:: SimplePublicKeyType ;
2829pub use signature:: { IdUri , Signatures } ;
2930use utils:: context:: DecodeSignDocCtx ;
3031
@@ -141,68 +142,62 @@ impl CatalystSignedDocument {
141142 /// # Errors
142143 ///
143144 /// Returns a report of verification failures and the source error.
144- #[ allow( clippy:: indexing_slicing) ]
145- pub fn verify < P > ( & self , pk_getter : P ) -> Result < ( ) , CatalystSignedDocError >
146- where P : Fn ( & IdUri ) -> SimplePublicKeyType {
147- let error_report = ProblemReport :: new ( "Catalyst Signed Document Verification" ) ;
148-
149- match self . as_cose_sign ( ) {
150- Ok ( cose_sign) => {
151- let signatures = self . signatures ( ) . cose_signatures ( ) ;
152- for ( idx, kid) in self . kids ( ) . iter ( ) . enumerate ( ) {
153- match pk_getter ( kid) {
154- SimplePublicKeyType :: Ed25519 ( pk) => {
155- let signature = & signatures[ idx] ;
156- let tbs_data = cose_sign. tbs_data ( & [ ] , signature) ;
157- match signature. signature . as_slice ( ) . try_into ( ) {
158- Ok ( signature_bytes) => {
159- let signature =
160- ed25519_dalek:: Signature :: from_bytes ( signature_bytes) ;
161- if let Err ( e) = pk. verify_strict ( & tbs_data, & signature) {
162- error_report. functional_validation (
163- & format ! (
164- "Verification failed for signature with Key ID {kid}: {e}"
165- ) ,
166- "During signature validation with verifying key" ,
167- ) ;
168- }
169- } ,
170- Err ( _) => {
171- error_report. invalid_value (
172- "cose signature" ,
173- & format ! ( "{}" , signature. signature. len( ) ) ,
174- & format ! ( "must be {}" , ed25519_dalek:: Signature :: BYTE_SIZE ) ,
175- "During encoding cose signature to bytes" ,
176- ) ;
177- } ,
145+ pub async fn verify < P , T > ( & self , pk_getter : P ) -> Result < ( ) , CatalystSignedDocError >
146+ where
147+ P : Fn ( & IdUri ) -> T ,
148+ T : Future < Output = Option < VerifyingKey > > ,
149+ {
150+ let report = ProblemReport :: new ( "Catalyst Signed Document Verification" ) ;
151+
152+ let cose_sign = match self . as_cose_sign ( ) {
153+ Ok ( cose_sign) => cose_sign,
154+ Err ( e) => {
155+ report. other (
156+ "Cannot build a COSE sign object" ,
157+ "During encoding signed document as COSE SIGN" ,
158+ ) ;
159+ return Err ( CatalystSignedDocError :: new ( report, e) ) ;
160+ } ,
161+ } ;
162+
163+ for ( signature, kid) in self . signatures ( ) . cose_signatures_with_kids ( ) {
164+ match pk_getter ( kid) . await {
165+ Some ( pk) => {
166+ let tbs_data = cose_sign. tbs_data ( & [ ] , signature) ;
167+ match signature. signature . as_slice ( ) . try_into ( ) {
168+ Ok ( signature_bytes) => {
169+ let signature = ed25519_dalek:: Signature :: from_bytes ( signature_bytes) ;
170+ if let Err ( e) = pk. verify_strict ( & tbs_data, & signature) {
171+ report. functional_validation (
172+ & format ! (
173+ "Verification failed for signature with Key ID {kid}: {e}"
174+ ) ,
175+ "During signature validation with verifying key" ,
176+ ) ;
178177 }
179178 } ,
180- SimplePublicKeyType :: Deleted => {
181- error_report. other (
182- & format ! ( "Public key for {kid} has been deleted." ) ,
183- "During public key extraction" ,
184- ) ;
185- } ,
186- SimplePublicKeyType :: Undefined => {
187- error_report. other (
188- & format ! ( "Public key for {kid} is undefined." ) ,
189- "During public key extraction" ,
179+ Err ( _) => {
180+ report. invalid_value (
181+ "cose signature" ,
182+ & format ! ( "{}" , signature. signature. len( ) ) ,
183+ & format ! ( "must be {}" , ed25519_dalek:: Signature :: BYTE_SIZE ) ,
184+ "During encoding cose signature to bytes" ,
190185 ) ;
191186 } ,
192187 }
193- }
194- } ,
195- Err ( e ) => {
196- error_report . other (
197- & format ! ( "{e}" ) ,
198- "During encoding signed document as COSE SIGN" ,
199- ) ;
200- } ,
188+ } ,
189+ None => {
190+ report . other (
191+ & format ! ( "Missing public key for {kid}." ) ,
192+ "During public key extraction" ,
193+ ) ;
194+ } ,
195+ }
201196 }
202197
203- if error_report . is_problematic ( ) {
198+ if report . is_problematic ( ) {
204199 return Err ( CatalystSignedDocError :: new (
205- error_report ,
200+ report ,
206201 anyhow:: anyhow!( "Verification failed for Catalyst Signed Document" ) ,
207202 ) ) ;
208203 }
@@ -222,10 +217,17 @@ impl CatalystSignedDocument {
222217
223218 /// Convert Catalyst Signed Document into `coset::CoseSign`
224219 fn as_cose_sign ( & self ) -> anyhow:: Result < coset:: CoseSign > {
225- let mut cose_bytes: Vec < u8 > = Vec :: new ( ) ;
226- minicbor:: encode ( self , & mut cose_bytes) ?;
227- coset:: CoseSign :: from_slice ( & cose_bytes)
228- . map_err ( |e| anyhow:: anyhow!( "encoding as COSE SIGN failed: {e}" ) )
220+ let protected_header = Header :: try_from ( & self . inner . metadata )
221+ . map_err ( |e| anyhow:: anyhow!( "Failed to encode Document Metadata: {e}" ) ) ?;
222+
223+ let mut builder = coset:: CoseSignBuilder :: new ( )
224+ . protected ( protected_header)
225+ . payload ( self . inner . content . encoded_bytes ( ) ?) ;
226+
227+ for signature in self . signatures ( ) . cose_signatures ( ) {
228+ builder = builder. add_signature ( signature) ;
229+ }
230+ Ok ( builder. build ( ) )
229231 }
230232}
231233
@@ -335,24 +337,7 @@ impl Encode<()> for CatalystSignedDocument {
335337 fn encode < W : minicbor:: encode:: Write > (
336338 & self , e : & mut encode:: Encoder < W > , _ctx : & mut ( ) ,
337339 ) -> Result < ( ) , encode:: Error < W :: Error > > {
338- let protected_header = Header :: try_from ( & self . inner . metadata ) . map_err ( |e| {
339- minicbor:: encode:: Error :: message ( format ! ( "Failed to encode Document Metadata: {e}" ) )
340- } ) ?;
341-
342- let mut builder = coset:: CoseSignBuilder :: new ( )
343- . protected ( protected_header)
344- . payload (
345- self . inner
346- . content
347- . encoded_bytes ( )
348- . map_err ( encode:: Error :: message) ?,
349- ) ;
350-
351- for signature in self . signatures ( ) . cose_signatures ( ) {
352- builder = builder. add_signature ( signature) ;
353- }
354-
355- let cose_sign = builder. build ( ) ;
340+ let cose_sign = self . as_cose_sign ( ) . map_err ( encode:: Error :: message) ?;
356341
357342 let cose_bytes = cose_sign. to_vec ( ) . map_err ( |e| {
358343 minicbor:: encode:: Error :: message ( format ! ( "Failed to encode COSE Sign document: {e}" ) )
@@ -423,8 +408,8 @@ mod tests {
423408 assert_eq ! ( decoded. doc_meta( ) , metadata. extra( ) ) ;
424409 }
425410
426- #[ test]
427- fn signature_verification_test ( ) {
411+ #[ tokio :: test]
412+ async fn signature_verification_test ( ) {
428413 let mut csprng = OsRng ;
429414 let sk: SigningKey = SigningKey :: generate ( & mut csprng) ;
430415 let content = serde_json:: to_vec ( & serde_json:: Value :: Null ) . unwrap ( ) ;
@@ -445,16 +430,8 @@ mod tests {
445430 . build ( )
446431 . unwrap ( ) ;
447432
448- assert ! ( signed_doc
449- . verify( |_| { SimplePublicKeyType :: Ed25519 ( pk) } )
450- . is_ok( ) ) ;
451-
452- assert ! ( signed_doc
453- . verify( |_| { SimplePublicKeyType :: Undefined } )
454- . is_err( ) ) ;
433+ assert ! ( signed_doc. verify( |_| async { Some ( pk) } ) . await . is_ok( ) ) ;
455434
456- assert ! ( signed_doc
457- . verify( |_| { SimplePublicKeyType :: Deleted } )
458- . is_err( ) ) ;
435+ assert ! ( signed_doc. verify( |_| async { None } ) . await . is_err( ) ) ;
459436 }
460437}
0 commit comments