guardian_client/keystore/
falcon.rs1use guardian_shared::SignatureScheme;
2use guardian_shared::hex::IntoHex;
3use miden_protocol::Word;
4use miden_protocol::crypto::dsa::falcon512_poseidon2::SecretKey;
5use miden_protocol::utils::serde::Serializable;
6
7use super::Signer;
8
9pub struct FalconKeyStore {
14 secret_key: SecretKey,
15 commitment: Word,
16 commitment_hex: String,
17 public_key_hex: String,
18}
19
20impl FalconKeyStore {
21 pub fn new(secret_key: SecretKey) -> Self {
23 let public_key = secret_key.public_key();
24 let commitment = public_key.to_commitment();
25 let commitment_hex = format!("0x{}", hex::encode(commitment.to_bytes()));
26 let public_key_hex = (&public_key).into_hex();
27
28 Self {
29 secret_key,
30 commitment,
31 commitment_hex,
32 public_key_hex,
33 }
34 }
35
36 pub fn generate() -> Self {
38 Self::new(SecretKey::new())
39 }
40}
41
42impl Signer for FalconKeyStore {
43 fn scheme(&self) -> SignatureScheme {
44 SignatureScheme::Falcon
45 }
46
47 fn commitment(&self) -> Word {
48 self.commitment
49 }
50
51 fn commitment_hex(&self) -> String {
52 self.commitment_hex.clone()
53 }
54
55 fn public_key_hex(&self) -> String {
56 self.public_key_hex.clone()
57 }
58
59 fn sign_word_hex(&self, message: Word) -> String {
60 self.secret_key.sign(message).into_hex()
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use guardian_shared::hex::FromHex;
67 use miden_protocol::crypto::dsa::falcon512_poseidon2::{PublicKey, Signature};
68
69 use super::*;
70
71 #[test]
72 fn generate_creates_valid_signer() {
73 let signer = FalconKeyStore::generate();
74 assert!(signer.commitment_hex().starts_with("0x"));
75 assert_eq!(signer.commitment_hex().len(), 66);
76 }
77
78 #[test]
79 fn new_from_secret_key_derives_correct_commitment() {
80 let secret_key = SecretKey::new();
81 let expected_commitment = secret_key.public_key().to_commitment();
82 let signer = FalconKeyStore::new(secret_key);
83 assert_eq!(signer.commitment(), expected_commitment);
84 }
85
86 #[test]
87 fn sign_word_produces_verifiable_signature() {
88 let signer = FalconKeyStore::generate();
89 let message = Word::default();
90 let signature_hex = signer.sign_word_hex(message);
91 let signature = Signature::from_hex(&signature_hex).unwrap();
92 let public_key = PublicKey::from_hex(&signer.public_key_hex()).unwrap();
93 assert!(public_key.verify(message, &signature));
94 }
95
96 #[test]
97 fn public_key_hex_roundtrips() {
98 let signer = FalconKeyStore::generate();
99 let public_key = PublicKey::from_hex(&signer.public_key_hex()).unwrap();
100 assert_eq!(public_key.to_commitment(), signer.commitment());
101 }
102}