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_time_subtraction)]
67 #![allow(clippy::useless_vec)]
68 #![allow(clippy::needless_pass_by_value)]
69 #![allow(clippy::string_slice)] use super::*;
72 use crate::SelfSigned;
73 use tor_llcrypto::pk::ValidatableSignature;
74
75 struct BadSig;
76 struct GoodSig;
77 impl ValidatableSignature for BadSig {
78 fn is_valid(&self) -> bool {
79 false
80 }
81 }
82 impl ValidatableSignature for GoodSig {
83 fn is_valid(&self) -> bool {
84 true
85 }
86 }
87
88 #[test]
89 fn test_sig_gated() {
90 let sg = SignatureGated::new(3_u32, Vec::new());
92 assert_eq!(sg.check_signature().unwrap(), 3_u32);
93
94 let sg = SignatureGated::new(77_u32, vec![Box::new(BadSig)]);
96 assert!(sg.check_signature().is_err());
97 let sg = SignatureGated::new(
98 77_u32,
99 vec![Box::new(GoodSig), Box::new(BadSig), Box::new(GoodSig)],
100 );
101 assert!(sg.check_signature().is_err());
102
103 let sg = SignatureGated::new(103_u32, vec![Box::new(GoodSig)]);
105 assert_eq!(sg.check_signature().unwrap(), 103_u32);
106 let sg = SignatureGated::new(
107 104_u32,
108 vec![Box::new(GoodSig), Box::new(GoodSig), Box::new(GoodSig)],
109 );
110 assert_eq!(sg.check_signature().unwrap(), 104_u32);
111 }
112
113 #[test]
114 fn test_map() {
115 let good = SignatureGated::new("hello world...", vec![Box::new(GoodSig)]);
116 let good = good.dangerously_map(|s| &s[..11]);
117 let s = good.check_signature().unwrap();
118 assert_eq!(s, "hello world");
119
120 let bad = SignatureGated::new("hello world...", vec![Box::new(BadSig)]);
121 let still_bad = bad.dangerously_map(|s| &s[..11]);
122 assert!(still_bad.check_signature().is_err());
123 }
124}