1use tor_llcrypto::pk::{self, ValidatableSignature};
4
5pub struct SignatureGated<T> {
8 obj: T,
11 signatures: Vec<Box<dyn ValidatableSignature>>,
14}
15
16impl<T> SignatureGated<T> {
17 pub fn new(obj: T, signatures: Vec<Box<dyn ValidatableSignature>>) -> Self {
20 SignatureGated { obj, signatures }
21 }
22
23 #[must_use]
30 pub fn dangerously_map<F, U>(self, f: F) -> SignatureGated<U>
31 where
32 F: FnOnce(T) -> U,
33 {
34 SignatureGated {
35 obj: f(self.obj),
36 signatures: self.signatures,
37 }
38 }
39}
40
41impl<T> super::SelfSigned<T> for SignatureGated<T> {
42 type Error = signature::Error;
43 fn dangerously_assume_wellsigned(self) -> T {
44 self.obj
45 }
46 fn is_well_signed(&self) -> Result<(), Self::Error> {
47 if pk::validate_all_sigs(&self.signatures[..]) {
48 Ok(())
49 } else {
50 Err(signature::Error::new())
51 }
52 }
53}
54
55#[cfg(test)]
56mod test {
57 #![allow(clippy::bool_assert_comparison)]
59 #![allow(clippy::clone_on_copy)]
60 #![allow(clippy::dbg_macro)]
61 #![allow(clippy::mixed_attributes_style)]
62 #![allow(clippy::print_stderr)]
63 #![allow(clippy::print_stdout)]
64 #![allow(clippy::single_char_pattern)]
65 #![allow(clippy::unwrap_used)]
66 #![allow(clippy::unchecked_duration_subtraction)]
67 #![allow(clippy::useless_vec)]
68 #![allow(clippy::needless_pass_by_value)]
69 use super::*;
71 use crate::SelfSigned;
72 use tor_llcrypto::pk::ValidatableSignature;
73
74 struct BadSig;
75 struct GoodSig;
76 impl ValidatableSignature for BadSig {
77 fn is_valid(&self) -> bool {
78 false
79 }
80 }
81 impl ValidatableSignature for GoodSig {
82 fn is_valid(&self) -> bool {
83 true
84 }
85 }
86
87 #[test]
88 fn test_sig_gated() {
89 let sg = SignatureGated::new(3_u32, Vec::new());
91 assert_eq!(sg.check_signature().unwrap(), 3_u32);
92
93 let sg = SignatureGated::new(77_u32, vec![Box::new(BadSig)]);
95 assert!(sg.check_signature().is_err());
96 let sg = SignatureGated::new(
97 77_u32,
98 vec![Box::new(GoodSig), Box::new(BadSig), Box::new(GoodSig)],
99 );
100 assert!(sg.check_signature().is_err());
101
102 let sg = SignatureGated::new(103_u32, vec![Box::new(GoodSig)]);
104 assert_eq!(sg.check_signature().unwrap(), 103_u32);
105 let sg = SignatureGated::new(
106 104_u32,
107 vec![Box::new(GoodSig), Box::new(GoodSig), Box::new(GoodSig)],
108 );
109 assert_eq!(sg.check_signature().unwrap(), 104_u32);
110 }
111
112 #[test]
113 fn test_map() {
114 let good = SignatureGated::new("hello world...", vec![Box::new(GoodSig)]);
115 let good = good.dangerously_map(|s| &s[..11]);
116 let s = good.check_signature().unwrap();
117 assert_eq!(s, "hello world");
118
119 let bad = SignatureGated::new("hello world...", vec![Box::new(BadSig)]);
120 let still_bad = bad.dangerously_map(|s| &s[..11]);
121 assert!(still_bad.check_signature().is_err());
122 }
123}