bc_envelope/extension/signature/signature_impl.rs
1use bc_components::{
2 DigestProvider, Signature, Signer, SigningOptions, Verifier,
3};
4#[cfg(feature = "known_value")]
5use known_values;
6
7use super::SignatureMetadata;
8use crate::{Envelope, EnvelopeEncodable, Error, Result};
9
10/// Support for signing envelopes and verifying signatures.
11///
12/// This implementation provides methods for digitally signing envelopes and
13/// verifying signatures. It supports both basic signatures and signatures with
14/// metadata, as well as multi-signature scenarios.
15impl Envelope {
16 /// Creates a signature for the envelope's subject and returns a new
17 /// envelope with a `'signed': Signature` assertion.
18 ///
19 /// - Parameters:
20 /// - private_key: The signer's `SigningPrivateKey`
21 ///
22 /// - Returns: The signed envelope.
23 pub fn add_signature(&self, private_key: &dyn Signer) -> Self {
24 self.add_signature_opt(private_key, None, None)
25 }
26
27 #[doc(hidden)]
28 /// Creates a signature for the envelope's subject and returns a new
29 /// envelope with a `'signed': Signature` assertion.
30 ///
31 /// - Parameters:
32 /// - private_key: A signer's `PrivateKeyBase` or `SigningPrivateKey`.
33 /// - options: Optional signing options.
34 /// - metadata: Optional metadata for the signature, which itself will be
35 /// signed.
36 ///
37 /// - Returns: The signed envelope.
38 pub fn add_signature_opt(
39 &self,
40 private_key: &dyn Signer,
41 options: Option<SigningOptions>,
42 metadata: Option<SignatureMetadata>,
43 ) -> Self {
44 let digest = *self.subject().digest().data();
45 let mut signature = Envelope::new(
46 private_key
47 .sign_with_options(&digest as &dyn AsRef<[u8]>, options.clone())
48 .unwrap(),
49 );
50
51 if let Some(metadata) = metadata
52 && metadata.has_assertions()
53 {
54 let mut signature_with_metadata = signature;
55
56 metadata.assertions().iter().for_each(|assertion| {
57 signature_with_metadata = signature_with_metadata
58 .add_assertion_envelope(assertion.to_envelope())
59 .unwrap();
60 });
61
62 signature_with_metadata = signature_with_metadata.wrap();
63
64 let outer_signature = Envelope::new(
65 private_key
66 .sign_with_options(
67 &signature_with_metadata.digest(),
68 options,
69 )
70 .unwrap(),
71 );
72 signature = signature_with_metadata
73 .add_assertion(known_values::SIGNED, outer_signature);
74 }
75
76 self.add_assertion(known_values::SIGNED, signature)
77 }
78
79 #[doc(hidden)]
80 /// Creates several signatures for the envelope's subject and returns a new
81 /// envelope with additional `'signed': Signature` assertions.
82 ///
83 /// - Parameters:
84 /// - private_keys: An array of signers' `SigningPrivateKey`s.
85 ///
86 /// - Returns: The signed envelope.
87 pub fn add_signatures(&self, private_keys: &[&dyn Signer]) -> Self {
88 private_keys
89 .iter()
90 .fold(self.clone(), |envelope, private_key| {
91 envelope.add_signature(*private_key)
92 })
93 }
94
95 #[doc(hidden)]
96 /// Creates several signatures for the envelope's subject and returns a new
97 /// envelope with additional `'signed': Signature` assertions.
98 ///
99 /// - Parameters:
100 /// - private_keys: An array of signers' `SigningPrivateKey`s and optional
101 /// `SigningOptions`.
102 ///
103 /// - Returns: The signed envelope.
104 pub fn add_signatures_opt(
105 &self,
106 private_keys: &[(
107 &dyn Signer,
108 Option<SigningOptions>,
109 Option<SignatureMetadata>,
110 )],
111 ) -> Self {
112 private_keys.iter().fold(
113 self.clone(),
114 |envelope, (private_key, options, metadata)| {
115 envelope.add_signature_opt(
116 *private_key,
117 options.clone(),
118 metadata.clone(),
119 )
120 },
121 )
122 }
123
124 /// Convenience constructor for a `'signed': Signature` assertion envelope.
125 ///
126 /// - Parameters:
127 /// - signature: The `Signature` for the object.
128 /// - note: An optional note to be added to the `Signature`.
129 ///
130 /// - Returns: The new assertion envelope.
131 pub fn make_signed_assertion(
132 &self,
133 signature: &Signature,
134 note: Option<&str>,
135 ) -> Self {
136 let mut envelope =
137 Envelope::new_assertion(known_values::SIGNED, signature.clone());
138 if let Some(note) = note {
139 envelope = envelope.add_assertion(known_values::NOTE, note);
140 }
141 envelope
142 }
143
144 /// Returns whether the given signature is valid.
145 ///
146 /// - Parameters:
147 /// - signature: The `Signature` to be checked.
148 /// - public_key: The potential signer's `Verifier`.
149 ///
150 /// - Returns: `true` if the signature is valid for this envelope's subject,
151 /// `false` otherwise.
152 pub fn is_verified_signature(
153 &self,
154 signature: &Signature,
155 public_key: &dyn Verifier,
156 ) -> bool {
157 self.is_signature_from_key(signature, public_key)
158 }
159
160 /// Checks whether the given signature is valid for the given public key.
161 ///
162 /// Used for chaining a series of operations that include validating
163 /// signatures.
164 ///
165 /// - Parameters:
166 /// - signature: The `Signature` to be checked.
167 /// - public_key: The potential signer's `Verifier`.
168 ///
169 /// - Returns: This envelope.
170 ///
171 /// - Throws: Throws `EnvelopeError.unverifiedSignature` if the signature is
172 /// not valid. valid.
173 pub fn verify_signature(
174 &self,
175 signature: &Signature,
176 public_key: &dyn Verifier,
177 ) -> Result<Self> {
178 if !self.is_signature_from_key(signature, public_key) {
179 return Err(Error::UnverifiedSignature);
180 }
181 Ok(self.clone())
182 }
183
184 /// Returns whether the envelope's subject has a valid signature from the
185 /// given public key.
186 ///
187 /// - Parameters:
188 /// - public_key: The potential signer's `Verifier`.
189 ///
190 /// - Returns: `true` if any signature is valid for this envelope's subject,
191 /// `false` otherwise.
192 ///
193 /// - Throws: Throws an exception if any `'signed'` assertion doesn't
194 /// contain a valid `Signature` as its object.
195 pub fn has_signature_from(
196 &self,
197 public_key: &dyn Verifier,
198 ) -> Result<bool> {
199 self.has_some_signature_from_key(public_key)
200 }
201
202 /// Returns whether the envelope's subject has a valid signature from the
203 /// given public key by returning the signature metadata.
204 ///
205 /// - Parameters:
206 /// - public_key: The potential signer's `Verifier`.
207 ///
208 /// - Returns: The metadata envelope if the signature is valid, `None`
209 /// otherwise.
210 pub fn has_signature_from_returning_metadata(
211 &self,
212 public_key: &dyn Verifier,
213 ) -> Result<Option<Envelope>> {
214 self.has_some_signature_from_key_returning_metadata(public_key)
215 }
216
217 /// Returns whether the envelope's subject has a valid signature from the
218 /// given public key.
219 ///
220 /// Used for chaining a series of operations that include validating
221 /// signatures.
222 ///
223 /// - Parameters:
224 /// - public_key: The potential signer's `Verifier`.
225 ///
226 /// - Returns: This envelope.
227 ///
228 /// - Throws: Throws `EnvelopeError.unverifiedSignature` if the signature is
229 /// not valid. valid.
230 pub fn verify_signature_from(
231 &self,
232 public_key: &dyn Verifier,
233 ) -> Result<Self> {
234 if !self.has_some_signature_from_key(public_key)? {
235 return Err(Error::UnverifiedSignature);
236 }
237 Ok(self.clone())
238 }
239
240 pub fn verify_signature_from_returning_metadata(
241 &self,
242 public_key: &dyn Verifier,
243 ) -> Result<Envelope> {
244 let metadata =
245 self.has_some_signature_from_key_returning_metadata(public_key)?;
246 if metadata.is_none() {
247 return Err(Error::UnverifiedSignature);
248 }
249 Ok(metadata.unwrap())
250 }
251
252 /// Checks whether the envelope's subject has a set of signatures.
253 pub fn has_signatures_from(
254 &self,
255 public_keys: &[&dyn Verifier],
256 ) -> Result<bool> {
257 self.has_signatures_from_threshold(public_keys, None)
258 }
259
260 /// Returns whether the envelope's subject has some threshold of signatures.
261 ///
262 /// If `threshold` is `nil`, then *all* signers in `public_keys` must have
263 /// signed. If `threshold` is `1`, then at least one signer must have
264 /// signed.
265 ///
266 /// - Parameters:
267 /// - public_keys: An array of potential signers' `Verifier`s.
268 /// - threshold: Optional minimum number of signers.
269 ///
270 /// - Returns: `true` if the threshold of valid signatures is met, `false`
271 /// otherwise.
272 ///
273 /// - Throws: Throws an exception if any `'signed'` assertion doesn't
274 /// contain a valid `Signature` as its object.
275 pub fn has_signatures_from_threshold(
276 &self,
277 public_keys: &[&dyn Verifier],
278 threshold: Option<usize>,
279 ) -> Result<bool> {
280 let threshold = threshold.unwrap_or(public_keys.len());
281 let mut count = 0;
282 for key in public_keys {
283 if self.clone().has_some_signature_from_key(*key)? {
284 count += 1;
285 if count >= threshold {
286 return Ok(true);
287 }
288 }
289 }
290 Ok(false)
291 }
292
293 /// Checks whether the envelope's subject has some threshold of signatures.
294 ///
295 /// If `threshold` is `nil`, then *all* signers in `public_keys` must have
296 /// signed. If `threshold` is `1`, then at least one signer must have
297 /// signed.
298 ///
299 /// Used for chaining a series of operations that include validating
300 /// signatures.
301 ///
302 /// - Parameters:
303 /// - public_keys: An array of potential signers' `Verifier`s.
304 /// - threshold: Optional minimum number of signers.
305 ///
306 /// - Returns: This envelope.
307 ///
308 /// - Throws: Throws an exception if the threshold of valid signatures is
309 /// not met.
310 pub fn verify_signatures_from_threshold(
311 &self,
312 public_keys: &[&dyn Verifier],
313 threshold: Option<usize>,
314 ) -> Result<Self> {
315 if !self.has_signatures_from_threshold(public_keys, threshold)? {
316 return Err(Error::UnverifiedSignature);
317 }
318 Ok(self.clone())
319 }
320
321 /// Checks whether the envelope's subject has a set of signatures.
322 pub fn verify_signatures_from(
323 &self,
324 public_keys: &[&dyn Verifier],
325 ) -> Result<Self> {
326 self.verify_signatures_from_threshold(public_keys, None)
327 }
328}
329
330/// Internal implementation details for signature operations.
331#[doc(hidden)]
332impl Envelope {
333 fn is_signature_from_key(
334 &self,
335 signature: &Signature,
336 key: &dyn Verifier,
337 ) -> bool {
338 key.verify(signature, &self.subject().digest())
339 }
340
341 fn has_some_signature_from_key(&self, key: &dyn Verifier) -> Result<bool> {
342 self.has_some_signature_from_key_returning_metadata(key)
343 .map(|x| x.is_some())
344 }
345
346 fn has_some_signature_from_key_returning_metadata(
347 &self,
348 key: &dyn Verifier,
349 ) -> Result<Option<Envelope>> {
350 // Valid signature objects are either:
351 //
352 // - `Signature` objects, or
353 // - `Signature` objects with additional metadata assertions, wrapped
354 // and then signed by the same key.
355 let signature_objects =
356 self.objects_for_predicate(known_values::SIGNED);
357 let result: Option<Result<Option<Envelope>>> =
358 signature_objects.iter().find_map(|signature_object| {
359 let signature_object_subject = signature_object.subject();
360 if signature_object_subject.is_wrapped() {
361 if let Ok(outer_signature_object) = signature_object
362 .object_for_predicate(known_values::SIGNED)
363 {
364 if let Ok(outer_signature) = outer_signature_object
365 .extract_subject::<Signature>(
366 ) {
367 if !signature_object_subject
368 .is_signature_from_key(&outer_signature, key)
369 {
370 return None;
371 }
372 } else {
373 return Some(Err(Error::InvalidOuterSignatureType));
374 }
375 }
376
377 let signature_metadata_envelope =
378 signature_object_subject.try_unwrap().unwrap();
379 if let Ok(signature) = signature_metadata_envelope
380 .extract_subject::<Signature>()
381 {
382 let signing_target = self.subject();
383 if !signing_target
384 .is_signature_from_key(&signature, key)
385 {
386 return Some(Err(Error::UnverifiedInnerSignature));
387 }
388 Some(Ok(Some(signature_metadata_envelope)))
389 } else {
390 Some(Err(Error::InvalidInnerSignatureType))
391 }
392 } else if let Ok(signature) =
393 signature_object.extract_subject::<Signature>()
394 {
395 if !self.is_signature_from_key(&signature, key) {
396 return None;
397 }
398 Some(Ok(Some(signature_object.clone())))
399 } else {
400 Some(Err(Error::InvalidSignatureType))
401 }
402 });
403
404 match result {
405 Some(Ok(Some(envelope))) => Ok(Some(envelope)),
406 Some(Err(err)) => Err(err),
407 _ => Ok(None),
408 }
409 }
410}
411
412/// Convenience methods for signing and verifying envelopes.
413///
414/// These methods provide a simpler API for common signature operations,
415/// particularly for signing entire envelopes by automatically wrapping them.
416impl Envelope {
417 /// Signs the entire envelope (subject and assertions) by wrapping it first.
418 ///
419 /// This is a convenience method that wraps the envelope before signing,
420 /// ensuring that all assertions are included in the signature, not just
421 /// the subject.
422 ///
423 /// # Parameters
424 ///
425 /// * `signer` - The signer that will produce the signature.
426 ///
427 /// # Returns
428 ///
429 /// A new envelope with the wrapped envelope as subject and a signature
430 /// assertion.
431 pub fn sign(&self, signer: &dyn Signer) -> Envelope {
432 self.sign_opt(signer, None)
433 }
434
435 /// Signs the entire envelope with options but no metadata.
436 ///
437 /// This is a convenience method that wraps the envelope before signing with
438 /// the specified options.
439 ///
440 /// # Parameters
441 ///
442 /// * `signer` - The signer that will produce the signature.
443 /// * `options` - Optional signing options to customize the signature
444 /// generation.
445 ///
446 /// # Returns
447 ///
448 /// A new envelope with the wrapped envelope as subject and a signature
449 /// assertion.
450 pub fn sign_opt(
451 &self,
452 signer: &dyn Signer,
453 options: Option<SigningOptions>,
454 ) -> Envelope {
455 self.wrap().add_signature_opt(signer, options, None)
456 }
457
458 /// Verifies that the envelope has a valid signature from the specified
459 /// verifier.
460 ///
461 /// This method assumes the envelope is wrapped (i.e., was signed using
462 /// `sign()` rather than `add_signature()`), and unwraps it after
463 /// verification.
464 ///
465 /// # Parameters
466 ///
467 /// * `verifier` - The verifier to check the signature against.
468 ///
469 /// # Returns
470 ///
471 /// The unwrapped envelope if verification succeeds, otherwise an error.
472 ///
473 /// # Errors
474 ///
475 /// Returns an error if the signature verification fails or if the envelope
476 /// cannot be unwrapped.
477 pub fn verify(&self, verifier: &dyn Verifier) -> Result<Envelope> {
478 self.verify_signature_from(verifier)?.try_unwrap()
479 }
480
481 /// Verifies the envelope's signature and returns both the unwrapped
482 /// envelope and signature metadata.
483 ///
484 /// This method verifies that the envelope has a valid signature from the
485 /// specified verifier, then unwraps it and returns both the envelope
486 /// and any metadata associated with the signature.
487 ///
488 /// # Parameters
489 ///
490 /// * `verifier` - The verifier to check the signature against.
491 ///
492 /// # Returns
493 ///
494 /// A tuple containing the unwrapped envelope and the signature metadata
495 /// envelope if verification succeeds, otherwise an error.
496 ///
497 /// # Errors
498 ///
499 /// Returns an error if the signature verification fails or if the envelope
500 /// cannot be unwrapped.
501 pub fn verify_returning_metadata(
502 &self,
503 verifier: &dyn Verifier,
504 ) -> Result<(Envelope, Envelope)> {
505 let metadata =
506 self.verify_signature_from_returning_metadata(verifier)?;
507 Ok((self.try_unwrap()?, metadata))
508 }
509}