|
1 | 1 | use hacspec_bip_340::*;
|
| 2 | +use hacspec_dev::rand::*; |
2 | 3 | use hacspec_halfagg::*;
|
3 | 4 | use hacspec_lib::*;
|
4 | 5 |
|
@@ -129,6 +130,60 @@ fn test_aggregate_verify() {
|
129 | 130 | }
|
130 | 131 | }
|
131 | 132 |
|
| 133 | +/// Constructs two invalid signatures whose aggregate signature is valid |
| 134 | +#[test] |
| 135 | +fn test_aggregate_verify_strange() { |
| 136 | + let mut pms_triples = Seq::<(PublicKey, Message, Signature)>::new(0); |
| 137 | + for i in 0..2 { |
| 138 | + let sk = [i as u8 + 1; 32]; |
| 139 | + let sk = SecretKey::from_public_array(sk); |
| 140 | + let msg = [i as u8 + 2; 32]; |
| 141 | + let msg = Message::from_public_array(msg); |
| 142 | + let aux_rand = [i as u8 + 3; 32]; |
| 143 | + let aux_rand = AuxRand::from_public_array(aux_rand); |
| 144 | + let sig = sign(msg, sk, aux_rand).unwrap(); |
| 145 | + pms_triples = pms_triples.push(&(pubkey_gen(sk).unwrap(), msg, sig)); |
| 146 | + } |
| 147 | + let aggsig = aggregate(&pms_triples).unwrap(); |
| 148 | + let pm_tuples = strip_sigs(&pms_triples); |
| 149 | + assert!(verify_aggregate(&aggsig, &pm_tuples).is_ok()); |
| 150 | + |
| 151 | + // Compute z values like in IncAggegrate |
| 152 | + let mut pmr = Seq::<(PublicKey, Message, Bytes32)>::new(0); |
| 153 | + let mut z = Seq::new(0); |
| 154 | + for i in 0..2 { |
| 155 | + let (pk, msg, sig) = pms_triples[i]; |
| 156 | + pmr = pmr.push(&(pk, msg, Bytes32::from_slice(&sig, 0, 32))); |
| 157 | + // TODO: The following line hashes i elements and therefore leads to |
| 158 | + // quadratic runtime. Instead, we should cache the intermediate result |
| 159 | + // and only hash the new element. |
| 160 | + z = z.push(&scalar_from_bytes(hash_halfagg( |
| 161 | + &Seq::<(PublicKey, Message, Bytes32)>::from_slice(&pmr, 0, i + 1), |
| 162 | + ))); |
| 163 | + } |
| 164 | + |
| 165 | + // Shift signatures appropriately |
| 166 | + let sagg = scalar_from_bytes(Bytes32::from_seq(&aggsig.slice(32 * 2, 32))); |
| 167 | + let s1: [u8; 32] = random_bytes(); |
| 168 | + let s1 = scalar_from_bytes(Bytes32::from_public_array(s1)); |
| 169 | + // Division is ordinary integer division, so use inv() explicitly |
| 170 | + let s0 = (sagg - z[1] * s1) * (z[0] as Scalar).inv(); |
| 171 | + |
| 172 | + let (pk0, msg0, sig0): (PublicKey, Message, Signature) = pms_triples[0]; |
| 173 | + let (pk1, msg1, sig1): (PublicKey, Message, Signature) = pms_triples[1]; |
| 174 | + let sig0_invalid = sig0.update(32, &bytes_from_scalar(s0)); |
| 175 | + let sig1_invalid = sig1.update(32, &bytes_from_scalar(s1)); |
| 176 | + assert!(!verify(msg0, pk0, sig0_invalid).is_ok()); |
| 177 | + assert!(!verify(msg1, pk1, sig1_invalid).is_ok()); |
| 178 | + |
| 179 | + let mut pms_strange = Seq::<(PublicKey, Message, Signature)>::new(0); |
| 180 | + pms_strange = pms_strange.push(&(pk0, msg0, sig0_invalid)); |
| 181 | + pms_strange = pms_strange.push(&(pk1, msg1, sig1_invalid)); |
| 182 | + let aggsig_strange = aggregate(&pms_strange).unwrap(); |
| 183 | + let pm_strange = strip_sigs(&pms_strange); |
| 184 | + assert!(verify_aggregate(&aggsig_strange, &pm_strange).is_ok()); |
| 185 | +} |
| 186 | + |
132 | 187 | #[test]
|
133 | 188 | fn test_edge_cases() {
|
134 | 189 | let empty_pm = Seq::<(PublicKey, Message)>::new(0);
|
|
0 commit comments