falcon_multisig/
keypair.rs1#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9
10use falcon_rust::falcon512::{self as fr, SecretKey as FrSecretKey};
11use rand::RngCore;
12use sha3::{Digest, Sha3_256};
13use zeroize::{Zeroize, ZeroizeOnDrop};
14
15use crate::{
16 error::Error,
17 verify::verify_raw,
18 DOMAIN_TAG, PUBLIC_KEY_BYTES,
19};
20
21#[derive(Clone, Debug, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct PublicKey(
32 #[cfg_attr(feature = "serde", serde(with = "hex_bytes"))]
33 Vec<u8>,
34);
35
36impl PublicKey {
37 pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, Error> {
39 if bytes.len() != PUBLIC_KEY_BYTES {
40 return Err(Error::InvalidPublicKeyLength {
41 expected: PUBLIC_KEY_BYTES,
42 actual: bytes.len(),
43 });
44 }
45 Ok(Self(bytes))
46 }
47
48 pub fn as_bytes(&self) -> &[u8] {
50 &self.0
51 }
52
53 pub fn into_bytes(self) -> Vec<u8> {
55 self.0
56 }
57
58 pub fn to_address(&self) -> crate::address::SingleKeyAddress {
63 crate::address::SingleKeyAddress::from_public_key(self)
64 }
65}
66
67pub struct KeyPair {
88 public_key: PublicKey,
89 secret_key: SecretKeyBytes,
90}
91
92#[derive(Zeroize, ZeroizeOnDrop)]
94struct SecretKeyBytes(Vec<u8>);
95
96impl KeyPair {
97 pub fn generate() -> Self {
102 let mut seed = [0u8; 32];
103 rand::thread_rng().fill_bytes(&mut seed);
104 let (sk, pk) = fr::keygen(seed);
105 Self {
106 public_key: PublicKey(pk.to_bytes().to_vec()),
107 secret_key: SecretKeyBytes(sk.to_bytes().to_vec()),
108 }
109 }
110
111 pub fn from_bytes(sk_bytes: &[u8], pk_bytes: &[u8]) -> Result<Self, Error> {
117 if pk_bytes.len() != PUBLIC_KEY_BYTES {
118 return Err(Error::InvalidPublicKeyLength {
119 expected: PUBLIC_KEY_BYTES,
120 actual: pk_bytes.len(),
121 });
122 }
123 Ok(Self {
124 public_key: PublicKey(pk_bytes.to_vec()),
125 secret_key: SecretKeyBytes(sk_bytes.to_vec()),
126 })
127 }
128
129 pub fn public_key(&self) -> &PublicKey {
131 &self.public_key
132 }
133
134 pub fn secret_key_bytes(&self) -> &[u8] {
139 &self.secret_key.0
140 }
141
142 pub fn sign(&self, message: &[u8]) -> Vec<u8> {
160 let digest = domain_hash(message);
161 let sk = FrSecretKey::from_bytes(&self.secret_key.0)
162 .expect("KeyPair::sign: stored secret key is malformed — this is a bug");
163 fr::sign(&digest, &sk).to_bytes().to_vec()
164 }
165
166 pub fn address(&self) -> crate::address::SingleKeyAddress {
168 self.public_key.to_address()
169 }
170
171 pub fn verify_own_signature(&self, message: &[u8], signature: &[u8]) -> Result<bool, Error> {
174 verify_raw(message, signature, self.public_key.as_bytes(), 0)
175 }
176}
177
178impl core::fmt::Debug for KeyPair {
179 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
180 f.debug_struct("KeyPair")
181 .field("public_key", &self.public_key)
182 .field("secret_key", &"[REDACTED]")
183 .finish()
184 }
185}
186
187#[cfg(feature = "serde")]
189impl serde::Serialize for KeyPair {
190 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
191 use serde::ser::SerializeStruct;
192 let mut state = serializer.serialize_struct("KeyPair", 1)?;
193 state.serialize_field("public_key", &self.public_key)?;
194 state.end()
195 }
196}
197
198pub(crate) fn domain_hash(message: &[u8]) -> [u8; 32] {
207 let mut hasher = Sha3_256::new();
208 hasher.update(DOMAIN_TAG);
209 hasher.update(message);
210 let result = hasher.finalize();
211 let mut out = [0u8; 32];
212 out.copy_from_slice(&result);
213 out
214}
215
216#[cfg(feature = "serde")]
221mod hex_bytes {
222 use serde::{Deserialize, Deserializer, Serializer};
223
224 #[cfg(not(feature = "std"))]
225 use alloc::vec::Vec;
226
227 pub fn serialize<S: Serializer>(bytes: &Vec<u8>, s: S) -> Result<S::Ok, S::Error> {
228 s.serialize_str(&hex::encode(bytes))
229 }
230
231 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
232 let s = String::deserialize(d)?;
233 hex::decode(&s).map_err(serde::de::Error::custom)
234 }
235}
236
237#[cfg(test)]
242mod tests {
243 use super::*;
244 use crate::{SIGNATURE_MAX_BYTES, SIGNATURE_MIN_BYTES};
245
246 #[test]
247 fn generate_and_sign_verify_roundtrip() {
248 let kp = KeyPair::generate();
249 let message = b"test payload for signing";
250 let sig = kp.sign(message);
251
252 assert!(sig.len() >= SIGNATURE_MIN_BYTES);
253 assert!(sig.len() <= SIGNATURE_MAX_BYTES);
254
255 let ok = kp.verify_own_signature(message, &sig).unwrap();
256 assert!(ok, "freshly generated signature must verify");
257 }
258
259 #[test]
260 fn wrong_message_fails_verification() {
261 let kp = KeyPair::generate();
262 let sig = kp.sign(b"correct message");
263 let ok = kp.verify_own_signature(b"wrong message", &sig).unwrap();
264 assert!(!ok);
265 }
266
267 #[test]
268 fn wrong_key_fails_verification() {
269 let kp1 = KeyPair::generate();
270 let kp2 = KeyPair::generate();
271 let message = b"some message";
272 let sig = kp1.sign(message);
273 let ok = verify_raw(message, &sig, kp2.public_key().as_bytes(), 0).unwrap();
275 assert!(!ok);
276 }
277
278 #[test]
279 fn public_key_length_is_correct() {
280 let kp = KeyPair::generate();
281 assert_eq!(kp.public_key().as_bytes().len(), PUBLIC_KEY_BYTES);
282 }
283
284 #[test]
285 fn from_bytes_rejects_bad_pk_length() {
286 let sk = KeyPair::generate();
287 let result = KeyPair::from_bytes(sk.secret_key_bytes(), &[0u8; 64]);
288 assert!(matches!(result, Err(Error::InvalidPublicKeyLength { .. })));
289 }
290
291 #[test]
292 fn debug_does_not_expose_secret_key() {
293 let kp = KeyPair::generate();
294 let debug_str = format!("{kp:?}");
295 assert!(debug_str.contains("[REDACTED]"));
296 assert!(!debug_str.contains("secret_key_bytes"));
297 }
298
299 #[test]
300 fn domain_hash_includes_tag() {
301 let with_tag = domain_hash(b"hello");
302 let mut hasher = Sha3_256::new();
304 hasher.update(b"hello");
305 let raw: [u8; 32] = hasher.finalize().into();
306 assert_ne!(with_tag, raw, "domain hash must differ from untagged hash");
307 }
308
309 #[test]
310 fn domain_hash_is_deterministic() {
311 assert_eq!(domain_hash(b"data"), domain_hash(b"data"));
312 }
313}