11
11
// specific language governing permissions and limitations under
12
12
// each license.
13
13
14
+ use std:: collections:: HashSet ;
15
+
14
16
use async_trait:: async_trait;
15
17
use c2pa:: dynamic_assertion:: {
16
18
AsyncDynamicAssertion , DynamicAssertion , DynamicAssertionContent , PartialClaim ,
@@ -34,7 +36,8 @@ use crate::{builder::AsyncCredentialHolder, IdentityAssertion, SignerPayload};
34
36
/// [`IdentityAssertionSigner`]: crate::builder::IdentityAssertionSigner
35
37
pub struct IdentityAssertionBuilder {
36
38
credential_holder : Box < dyn CredentialHolder > ,
37
- // referenced_assertions: Vec<MumbleSomething>,
39
+ referenced_assertions : HashSet < String > ,
40
+ roles : Vec < String > ,
38
41
}
39
42
40
43
impl IdentityAssertionBuilder {
@@ -43,6 +46,30 @@ impl IdentityAssertionBuilder {
43
46
pub fn for_credential_holder < CH : CredentialHolder + ' static > ( credential_holder : CH ) -> Self {
44
47
Self {
45
48
credential_holder : Box :: new ( credential_holder) ,
49
+ referenced_assertions : HashSet :: new ( ) ,
50
+ roles : vec ! [ ] ,
51
+ }
52
+ }
53
+
54
+ /// Add assertion labels to consider as referenced_assertions.
55
+ ///
56
+ /// If any of these labels match assertions that are present in the partial
57
+ /// claim submitted during signing, they will be added to the
58
+ /// `referenced_assertions` list for this identity assertion.
59
+ pub fn add_referenced_assertions ( & mut self , labels : & [ & str ] ) {
60
+ for label in labels {
61
+ self . referenced_assertions . insert ( label. to_string ( ) ) ;
62
+ }
63
+ }
64
+
65
+ /// Add roles to attach to the named actor for this identity assertion.
66
+ ///
67
+ /// See [§5.1.2, “Named actor roles,”] for more information.
68
+ ///
69
+ /// [§5.1.2, “Named actor roles,”]: https://cawg.io/identity/1.1-draft/#_named_actor_roles
70
+ pub fn add_roles ( & mut self , roles : & [ & str ] ) {
71
+ for role in roles {
72
+ self . roles . push ( role. to_string ( ) ) ;
46
73
}
47
74
}
48
75
}
@@ -64,20 +91,31 @@ impl DynamicAssertion for IdentityAssertionBuilder {
64
91
size : Option < usize > ,
65
92
claim : & PartialClaim ,
66
93
) -> c2pa:: Result < DynamicAssertionContent > {
67
- // TO DO: Better filter for referenced assertions.
68
- // For now, just require hard binding.
69
-
70
94
// TO DO: Update to respond correctly when identity assertions refer to each
71
95
// other.
72
96
let referenced_assertions = claim
73
97
. assertions ( )
74
- . filter ( |a| a. url ( ) . contains ( "c2pa.assertions/c2pa.hash." ) )
98
+ . filter ( |a| {
99
+ // Always accept the hard binding assertion.
100
+ if a. url ( ) . contains ( "c2pa.assertions/c2pa.hash." ) {
101
+ return true ;
102
+ }
103
+
104
+ let label = if let Some ( ( _, label) ) = a. url ( ) . rsplit_once ( '/' ) {
105
+ label. to_string ( )
106
+ } else {
107
+ a. url ( )
108
+ } ;
109
+
110
+ self . referenced_assertions . contains ( & label)
111
+ } )
75
112
. cloned ( )
76
113
. collect ( ) ;
77
114
78
115
let signer_payload = SignerPayload {
79
116
referenced_assertions,
80
117
sig_type : self . credential_holder . sig_type ( ) . to_owned ( ) ,
118
+ roles : self . roles . clone ( ) ,
81
119
} ;
82
120
83
121
let signature_result = self . credential_holder . sign ( & signer_payload) ;
@@ -100,7 +138,9 @@ pub struct AsyncIdentityAssertionBuilder {
100
138
101
139
#[ cfg( target_arch = "wasm32" ) ]
102
140
credential_holder : Box < dyn AsyncCredentialHolder > ,
103
- // referenced_assertions: Vec<MumbleSomething>,
141
+
142
+ referenced_assertions : HashSet < String > ,
143
+ roles : Vec < String > ,
104
144
}
105
145
106
146
impl AsyncIdentityAssertionBuilder {
@@ -111,6 +151,30 @@ impl AsyncIdentityAssertionBuilder {
111
151
) -> Self {
112
152
Self {
113
153
credential_holder : Box :: new ( credential_holder) ,
154
+ referenced_assertions : HashSet :: new ( ) ,
155
+ roles : vec ! [ ] ,
156
+ }
157
+ }
158
+
159
+ /// Add assertion labels to consider as referenced_assertions.
160
+ ///
161
+ /// If any of these labels match assertions that are present in the partial
162
+ /// claim submitted during signing, they will be added to the
163
+ /// `referenced_assertions` list for this identity assertion.
164
+ pub fn add_referenced_assertions ( & mut self , labels : & [ & str ] ) {
165
+ for label in labels {
166
+ self . referenced_assertions . insert ( label. to_string ( ) ) ;
167
+ }
168
+ }
169
+
170
+ /// Add roles to attach to the named actor for this identity assertion.
171
+ ///
172
+ /// See [§5.1.2, “Named actor roles,”] for more information.
173
+ ///
174
+ /// [§5.1.2, “Named actor roles,”]: https://cawg.io/identity/1.1-draft/#_named_actor_roles
175
+ pub fn add_roles ( & mut self , roles : & [ & str ] ) {
176
+ for role in roles {
177
+ self . roles . push ( role. to_string ( ) ) ;
114
178
}
115
179
}
116
180
}
@@ -134,20 +198,31 @@ impl AsyncDynamicAssertion for AsyncIdentityAssertionBuilder {
134
198
size : Option < usize > ,
135
199
claim : & PartialClaim ,
136
200
) -> c2pa:: Result < DynamicAssertionContent > {
137
- // TO DO: Better filter for referenced assertions.
138
- // For now, just require hard binding.
139
-
140
201
// TO DO: Update to respond correctly when identity assertions refer to each
141
202
// other.
142
203
let referenced_assertions = claim
143
204
. assertions ( )
144
- . filter ( |a| a. url ( ) . contains ( "c2pa.assertions/c2pa.hash." ) )
205
+ . filter ( |a| {
206
+ // Always accept the hard binding assertion.
207
+ if a. url ( ) . contains ( "c2pa.assertions/c2pa.hash." ) {
208
+ return true ;
209
+ }
210
+
211
+ let label = if let Some ( ( _, label) ) = a. url ( ) . rsplit_once ( '/' ) {
212
+ label. to_string ( )
213
+ } else {
214
+ a. url ( )
215
+ } ;
216
+
217
+ self . referenced_assertions . contains ( & label)
218
+ } )
145
219
. cloned ( )
146
220
. collect ( ) ;
147
221
148
222
let signer_payload = SignerPayload {
149
223
referenced_assertions,
150
224
sig_type : self . credential_holder . sig_type ( ) . to_owned ( ) ,
225
+ roles : self . roles . clone ( ) ,
151
226
} ;
152
227
153
228
let signature_result = self . credential_holder . sign ( & signer_payload) . await ;
0 commit comments