mldsa_native_rs/
wrapper.rs1pub use signature;
2
3use crate::ffi;
4
5pub mod parameter_sets;
7
8mod signature_encoding;
9mod signing_key;
10mod verifying_key;
11
12pub use signature_encoding::*;
13pub use signing_key::*;
14pub use verifying_key::*;
15
16pub(crate) mod utils;
17pub use transcoding::*;
18pub use utils::transcoding;
19
20trait FFIFunctionPointers {
22 const KEYGEN_FROM_SEED_FN: unsafe extern "C" fn(
23 pk: *mut u8,
24 sk: *mut u8,
25 seed: *const u8,
26 ) -> ffi::c_int;
27 const PK_FROM_SK_FN: unsafe extern "C" fn(pk: *mut u8, sk: *const u8) -> ffi::c_int;
28 const SIGN_WITH_SEED_FN: unsafe extern "C" fn(
29 sig: *mut u8,
30 siglen: *mut usize,
31 m: *const u8,
32 mlen: usize,
33 pre: *const u8,
34 prelen: usize,
35 rnd: *const u8,
36 sk: *const u8,
37 externalmu: ffi::c_int,
38 ) -> ffi::c_int;
39 const VERIFY_FN: unsafe extern "C" fn(
40 sig: *const u8,
41 siglen: usize,
42 m: *const u8,
43 mlen: usize,
44 ctx: *const u8,
45 ctxlen: usize,
46 pk: *const u8,
47 ) -> ffi::c_int;
48 const PREPARE_DOMAIN_SEPARATION_PREFIX_FN: unsafe extern "C" fn(
49 prefix: *mut u8,
50 ph: *const u8,
51 phlen: usize,
52 ctx: *const u8,
53 ctxlen: usize,
54 hashalg: ffi::c_int,
55 ) -> usize;
56}
57
58pub trait SigningKeyLen {
60 const SIGNING_KEY_LEN: usize;
64
65 const SECRET_KEY_LEN: usize = Self::SIGNING_KEY_LEN;
69
70 type LEN: generic_array::ArrayLength;
72}
73
74pub trait VerifyingKeyLen {
76 const VERIFYING_KEY_LEN: usize;
80
81 const PUBLIC_KEY_LEN: usize = Self::VERIFYING_KEY_LEN;
85
86 type LEN: generic_array::ArrayLength;
88}
89
90pub trait SignatureLen {
92 const SIGNATURE_LEN: usize;
94
95 type LEN: generic_array::ArrayLength;
97}
98
99pub trait SeedLen {
101 const SEED_LEN: usize;
103
104 type LEN: generic_array::ArrayLength;
106}
107
108#[allow(private_bounds)]
110pub trait ParameterSet:
111 FFIFunctionPointers
112 + SigningKeyLen
113 + VerifyingKeyLen
114 + SignatureLen
115 + SeedLen
116 + PartialEq
117 + Eq
118 + Clone
119 + core::fmt::Debug
120{
121 const NAME: &'static str;
123}
124
125#[derive(Debug)]
127pub struct FFIError {
128 pub code: ffi::c_int,
130}
131
132impl std::fmt::Display for FFIError {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 write!(f, "{self:?}")
136 }
137}
138
139impl std::error::Error for FFIError {}
140
141use signature::Keypair;
142impl<P: ParameterSet> Keypair for SigningKey<P> {
143 type VerifyingKey = VerifyingKey<P>;
144
145 fn verifying_key(&self) -> Self::VerifyingKey {
146 match pk_from_sk(self) {
147 Ok(vk) => vk,
148 Err(_) => unreachable!(),
149 }
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use signature::Signer;
156
157 use super::*;
158
159 fn test_sign_verify_tampered_generic<P: ParameterSet>() {
160 let seed = utils::rand::random_generic_byte_array();
161 let (sk, vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
162 std::println!("{sk:?}");
163 std::println!("{vk:?}");
164 let msg = b"Hello world!";
165 let sig = sk.try_sign(msg).unwrap();
166 let other_msg = b"Hello Earth!";
167 assert!(vk.verify(other_msg, &sig).is_err());
168 }
169
170 fn test_sign_verify_generic<P: ParameterSet>() {
171 let seed = utils::rand::random_generic_byte_array();
172 let (sk, vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
173 std::println!("{sk:?}");
174 std::println!("{vk:?}");
175 let msg = b"Hello world!";
176 let sig = sk.try_sign(msg).unwrap();
177 vk.verify(msg, &sig).unwrap();
178 }
179
180 fn test_recover_verifying_key_generic<P: ParameterSet>() {
181 let seed = utils::rand::random_generic_byte_array();
182 let (sk, vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
183 let vk2 = sk.verifying_key();
184 assert_eq!(vk, vk2);
185 }
186
187 fn test_keygen_from_seed_generic<P: ParameterSet>() {
188 let seed = utils::rand::random_generic_byte_array();
189 let (_sk, _vk) = signing_key::keygen_from_seed::<P>(&seed).expect("Keygen failed");
190 }
191
192 #[test]
193 fn test_sign_verify() {
194 test_sign_verify_generic::<parameter_sets::ML_DSA_44>();
195 test_sign_verify_generic::<parameter_sets::ML_DSA_65>();
196 test_sign_verify_generic::<parameter_sets::ML_DSA_87>();
197 }
198
199 #[test]
200 fn test_sign_verify_tampered() {
201 test_sign_verify_tampered_generic::<parameter_sets::ML_DSA_44>();
202 test_sign_verify_tampered_generic::<parameter_sets::ML_DSA_65>();
203 test_sign_verify_tampered_generic::<parameter_sets::ML_DSA_87>();
204 }
205
206 #[test]
207 fn test_recover_verifying_key() {
208 test_recover_verifying_key_generic::<parameter_sets::ML_DSA_44>();
209 test_recover_verifying_key_generic::<parameter_sets::ML_DSA_65>();
210 test_recover_verifying_key_generic::<parameter_sets::ML_DSA_87>();
211 }
212
213 #[test]
214 fn test_keygen_from_seed() {
215 test_keygen_from_seed_generic::<parameter_sets::ML_DSA_44>();
216 test_keygen_from_seed_generic::<parameter_sets::ML_DSA_65>();
217 test_keygen_from_seed_generic::<parameter_sets::ML_DSA_87>();
218 }
219}