@@ -17,6 +17,8 @@ use c2pa::{
1717 identity:: { builder:: AsyncCredentialHolder , SignerPayload } ,
1818} ;
1919use neon:: prelude:: * ;
20+ use serde:: { Deserialize , Serialize } ;
21+ use serde_bytes:: ByteBuf ;
2022use std:: ops:: Deref ;
2123use std:: sync:: RwLock ;
2224
@@ -28,6 +30,22 @@ pub struct NeonIdentityAssertionBuilder {
2830 roles : RwLock < Vec < String > > ,
2931}
3032
33+ #[ derive( Deserialize , Serialize ) ]
34+ struct IdentityAssertion {
35+ signer_payload : SignerPayload ,
36+
37+ signature : Vec < u8 > ,
38+
39+ pad1 : Vec < u8 > ,
40+
41+ // Must use explicit ByteBuf here because #[serde(with = "serde_bytes")]
42+ // does not work with Option<Vec<u8>>.
43+ pad2 : Option < ByteBuf > ,
44+
45+ // Label for the assertion. Only assigned when reading from a manifest.
46+ label : Option < String > ,
47+ }
48+
3149// Note: unwrap is used on read() and write() results, as poisoning only occurs as a result of a
3250// panic on another thread.
3351impl Clone for NeonIdentityAssertionBuilder {
@@ -108,9 +126,11 @@ impl AsyncDynamicAssertion for NeonIdentityAssertionBuilder {
108126 let referenced_assertions = claim
109127 . assertions ( )
110128 . filter ( |a| {
129+ // Always include hash data assertions
111130 if a. url ( ) . contains ( "c2pa.assertions/c2pa.hash." ) {
112131 return true ;
113132 }
133+ // Otherwise include if user-added label matches
114134 let label = if let Some ( ( _, label) ) = a. url ( ) . rsplit_once ( '/' ) {
115135 label. to_string ( )
116136 } else {
@@ -138,20 +158,52 @@ impl AsyncDynamicAssertion for NeonIdentityAssertionBuilder {
138158 . await
139159 . map_err ( |e| c2pa:: Error :: OtherError ( Box :: new ( e) ) ) ?;
140160
141- let mut assertion_cbor: Vec < u8 > = vec ! [ ] ;
142- ciborium:: into_writer ( & ( signer_payload, signature) , & mut assertion_cbor)
161+ finalize_identity_assertion ( signer_payload, size, signature)
162+ }
163+ }
164+ fn finalize_identity_assertion (
165+ signer_payload : SignerPayload ,
166+ size : Option < usize > ,
167+ signature : Vec < u8 > ,
168+ ) -> c2pa:: Result < DynamicAssertionContent > {
169+ let mut ia = IdentityAssertion {
170+ signer_payload,
171+ signature,
172+ pad1 : vec ! [ ] ,
173+ pad2 : None ,
174+ label : None ,
175+ } ;
176+
177+ let mut assertion_cbor: Vec < u8 > = vec ! [ ] ;
178+ ciborium:: into_writer ( & ia, & mut assertion_cbor)
179+ . map_err ( |e| c2pa:: Error :: BadParam ( e. to_string ( ) ) ) ?;
180+ // TO DO: Think through how errors map into crate::Error.
181+
182+ if let Some ( assertion_size) = size {
183+ if assertion_cbor. len ( ) > assertion_size {
184+ return Err ( c2pa:: Error :: BadParam ( format ! ( "Serialized assertion is {len} bytes, which exceeds the planned size of {assertion_size} bytes" , len = assertion_cbor. len( ) ) ) ) ;
185+ }
186+
187+ ia. pad1 = vec ! [ 0u8 ; assertion_size - assertion_cbor. len( ) - 15 ] ;
188+
189+ assertion_cbor. clear ( ) ;
190+ ciborium:: into_writer ( & ia, & mut assertion_cbor)
143191 . map_err ( |e| c2pa:: Error :: BadParam ( e. to_string ( ) ) ) ?;
192+ // TO DO: Think through how errors map into crate::Error.
144193
145- if let Some ( assertion_size) = size {
146- if assertion_cbor. len ( ) > assertion_size {
147- return Err ( c2pa:: Error :: BadParam ( format ! (
148- "Serialized assertion is {} bytes, which exceeds the planned size of {} bytes" ,
149- assertion_cbor. len( ) ,
150- assertion_size
151- ) ) ) ;
152- }
153- }
194+ ia. pad2 = Some ( ByteBuf :: from ( vec ! [
195+ 0u8 ;
196+ assertion_size - assertion_cbor. len( ) - 6
197+ ] ) ) ;
154198
155- Ok ( DynamicAssertionContent :: Cbor ( assertion_cbor) )
199+ assertion_cbor. clear ( ) ;
200+ ciborium:: into_writer ( & ia, & mut assertion_cbor)
201+ . map_err ( |e| c2pa:: Error :: BadParam ( e. to_string ( ) ) ) ?;
202+ // TO DO: Think through how errors map into crate::Error.
203+
204+ // TO DO: See if this approach ever fails. IMHO it "should" work for all cases.
205+ assert_eq ! ( assertion_size, assertion_cbor. len( ) ) ;
156206 }
207+
208+ Ok ( DynamicAssertionContent :: Cbor ( assertion_cbor) )
157209}
0 commit comments