hash_based_signatures/signature/
q_indexed_signature.rs1use crate::merkle_tree::{MerkleProof, MerkleTree};
2use crate::signature::winternitz::d::D;
3use crate::signature::winternitz::{WinternitzKey, WinternitzSignature, WinternitzSignatureScheme};
4use crate::signature::{HashType, SignatureScheme};
5use rand::prelude::*;
6use rand_chacha::ChaCha20Rng;
7use serde::{Deserialize, Serialize};
8
9#[derive(Clone)]
41pub struct QIndexedSignatureScheme {
42 one_time_signatures: Vec<WinternitzSignatureScheme>,
43 public_key_merkle_tree: MerkleTree<WinternitzKey>,
44}
45
46#[derive(PartialEq, Serialize, Deserialize)]
47pub struct QIndexedSignature {
48 pub proof: MerkleProof<WinternitzKey>,
54
55 pub one_time_signature: WinternitzSignature,
57}
58
59impl QIndexedSignatureScheme {
60 pub fn new(q: usize, seed: [u8; 32], d: D) -> Self {
66 let mut rng = ChaCha20Rng::from_seed(seed);
67 let mut seed_for_sub_scheme: [u8; 32] = [0; 32];
68 let mut one_time_signatures = Vec::new();
69 for _ in 0..q {
70 rng.fill_bytes(&mut seed_for_sub_scheme);
71 one_time_signatures.push(WinternitzSignatureScheme::new(seed_for_sub_scheme, d));
72 }
73
74 let public_keys: Vec<WinternitzKey> =
75 one_time_signatures.iter().map(|s| s.public_key()).collect();
76
77 let public_key_merkle_tree = MerkleTree::new(&public_keys);
78
79 Self {
80 one_time_signatures,
81 public_key_merkle_tree,
82 }
83 }
84}
85
86impl SignatureScheme<HashType, (usize, HashType), QIndexedSignature> for QIndexedSignatureScheme {
87 fn public_key(&self) -> HashType {
88 *self.public_key_merkle_tree.get_root_hash()
89 }
90
91 fn sign(&mut self, message: (usize, HashType)) -> QIndexedSignature {
100 let (i, message) = message;
101 let proof = self.public_key_merkle_tree.get_proof(i);
102 QIndexedSignature {
103 proof,
104 one_time_signature: self.one_time_signatures[i].sign(message),
105 }
106 }
107
108 fn verify(pk: HashType, message: (usize, HashType), signature: &QIndexedSignature) -> bool {
109 let (i_m, message) = message;
110
111 if i_m != signature.proof.index {
112 return false;
113 }
114
115 match WinternitzSignatureScheme::public_key_from_message_and_signature(
121 message,
122 &signature.one_time_signature,
123 ) {
124 Err(_) => false,
125 Ok(winternitz_pk) => signature.proof.verify(pk, &winternitz_pk),
126 }
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use crate::signature::q_indexed_signature::QIndexedSignatureScheme;
133 use crate::signature::winternitz::d::D;
134 use crate::signature::SignatureScheme;
135
136 fn get_signature_scheme() -> QIndexedSignatureScheme {
137 let seed = [0u8; 32];
138 QIndexedSignatureScheme::new(4, seed, D::new(255))
139 }
140
141 #[test]
142 fn test_correct_signatures() {
143 let mut signature_scheme = get_signature_scheme();
144
145 let signature0 = signature_scheme.sign((0, [0u8; 32]));
146 assert!(QIndexedSignatureScheme::verify(
147 signature_scheme.public_key(),
148 (0, [0u8; 32]),
149 &signature0
150 ));
151
152 let signature3 = signature_scheme.sign((3, [3u8; 32]));
153 assert!(QIndexedSignatureScheme::verify(
154 signature_scheme.public_key(),
155 (3, [3u8; 32]),
156 &signature3
157 ))
158 }
159
160 #[test]
161 fn test_incorrect_signature() {
162 let mut signature_scheme = get_signature_scheme();
163 let signature = signature_scheme.sign((0, [0u8; 32]));
164 assert!(!QIndexedSignatureScheme::verify(
165 signature_scheme.public_key(),
166 (0, [1u8; 32]), &signature
168 ));
169 assert!(!QIndexedSignatureScheme::verify(
170 signature_scheme.public_key(),
171 (1, [0u8; 32]), &signature
173 ))
174 }
175
176 #[test]
177 fn test_can_sign_same_message() {
178 let mut signature_scheme = get_signature_scheme();
179 signature_scheme.sign((0, [0u8; 32]));
180 signature_scheme.sign((0, [0u8; 32]));
181 }
182}