pqcrypto_qtesla/
qteslapiii.rs1use crate::ffi;
20use pqcrypto_traits::sign as primitive;
21use pqcrypto_traits::{Error, Result};
22
23macro_rules! simple_struct {
24 ($type: ident, $size: expr) => {
25 #[derive(Clone, Copy)]
26 pub struct $type([u8; $size]);
27
28 impl $type {
29 fn new() -> Self {
35 $type([0u8; $size])
36 }
37 }
38
39 impl primitive::$type for $type {
40 #[inline]
42 fn as_bytes(&self) -> &[u8] {
43 &self.0
44 }
45
46 fn from_bytes(bytes: &[u8]) -> Result<Self> {
48 if bytes.len() != $size {
49 Err(Error::BadLength {
50 name: stringify!($type),
51 actual: bytes.len(),
52 expected: $size,
53 })
54 } else {
55 let mut array = [0u8; $size];
56 array.copy_from_slice(bytes);
57 Ok($type(array))
58 }
59 }
60 }
61
62 impl PartialEq for $type {
63 fn eq(&self, other: &Self) -> bool {
65 self.0
66 .iter()
67 .zip(other.0.iter())
68 .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) })
69 .is_ok()
70 }
71 }
72 };
73}
74
75simple_struct!(
76 PublicKey,
77 ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_PUBLICKEYBYTES
78);
79simple_struct!(
80 SecretKey,
81 ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_SECRETKEYBYTES
82);
83#[derive(Clone, Copy)]
84pub struct DetachedSignature([u8; ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES], usize);
85
86impl DetachedSignature {
88 fn new() -> Self {
89 DetachedSignature([0u8; ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES], 0)
90 }
91}
92
93impl primitive::DetachedSignature for DetachedSignature {
94 #[inline]
96 fn as_bytes(&self) -> &[u8] {
97 &self.0[..self.1]
98 }
99
100 #[inline]
101 fn from_bytes(bytes: &[u8]) -> Result<Self> {
102 let actual = bytes.len();
103 let expected = ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES;
104 if actual > expected {
105 return Err(Error::BadLength {
106 name: "DetachedSignature",
107 actual,
108 expected,
109 });
110 }
111 let mut array = [0u8; ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES];
112 array[..bytes.len()].copy_from_slice(bytes);
113 Ok(DetachedSignature(array, actual))
114 }
115}
116
117#[derive(Clone)]
118pub struct SignedMessage(Vec<u8>);
119impl primitive::SignedMessage for SignedMessage {
120 #[inline]
122 fn as_bytes(&self) -> &[u8] {
123 &self.0.as_slice()
124 }
125
126 #[inline]
128 fn from_bytes(bytes: &[u8]) -> Result<Self> {
129 Ok(SignedMessage(bytes.to_vec()))
130 }
131}
132
133impl SignedMessage {
134 pub fn len(&self) -> usize {
135 self.0.len()
136 }
137}
138
139pub const fn public_key_bytes() -> usize {
141 ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_PUBLICKEYBYTES
142}
143
144pub const fn secret_key_bytes() -> usize {
146 ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_SECRETKEYBYTES
147}
148
149pub const fn signature_bytes() -> usize {
151 ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES
152}
153
154pub fn keypair() -> (PublicKey, SecretKey) {
156 keypair_portable()
157}
158
159#[inline]
160fn keypair_portable() -> (PublicKey, SecretKey) {
161 let mut pk = PublicKey::new();
162 let mut sk = SecretKey::new();
163 assert_eq!(
164 unsafe {
165 ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_keypair(pk.0.as_mut_ptr(), sk.0.as_mut_ptr())
166 },
167 0
168 );
169 (pk, sk)
170}
171
172pub fn sign(msg: &[u8], sk: &SecretKey) -> SignedMessage {
174 sign_portable(msg, sk)
175}
176
177#[inline]
178fn sign_portable(msg: &[u8], sk: &SecretKey) -> SignedMessage {
179 let max_len = msg.len() + signature_bytes();
180 let mut signed_msg = Vec::with_capacity(max_len);
181 let mut smlen: usize = 0;
182 unsafe {
183 ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign(
184 signed_msg.as_mut_ptr(),
185 &mut smlen as *mut usize,
186 msg.as_ptr(),
187 msg.len(),
188 sk.0.as_ptr(),
189 );
190 debug_assert!(smlen <= max_len, "exceeded Vec capacity");
191 signed_msg.set_len(smlen);
192 }
193 SignedMessage(signed_msg)
194}
195
196#[must_use]
197pub fn open(
198 sm: &SignedMessage,
199 pk: &PublicKey,
200) -> std::result::Result<Vec<u8>, primitive::VerificationError> {
201 open_portable(sm, pk)
202}
203
204#[inline]
205fn open_portable(
206 sm: &SignedMessage,
207 pk: &PublicKey,
208) -> std::result::Result<Vec<u8>, primitive::VerificationError> {
209 let mut m: Vec<u8> = Vec::with_capacity(sm.len());
210 let mut mlen: usize = 0;
211 match unsafe {
212 ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_open(
213 m.as_mut_ptr(),
214 &mut mlen as *mut usize,
215 sm.0.as_ptr(),
216 sm.len(),
217 pk.0.as_ptr(),
218 )
219 } {
220 0 => {
221 unsafe { m.set_len(mlen) };
222 Ok(m)
223 }
224 -1 => Err(primitive::VerificationError::InvalidSignature),
225 _ => Err(primitive::VerificationError::UnknownVerificationError),
226 }
227}
228
229pub fn detached_sign(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
230 detached_sign_portable(msg, sk)
231}
232
233#[inline]
234fn detached_sign_portable(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
235 let mut sig = DetachedSignature::new();
236 unsafe {
237 ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_signature(
238 sig.0.as_mut_ptr(),
239 &mut sig.1 as *mut usize,
240 msg.as_ptr(),
241 msg.len(),
242 sk.0.as_ptr(),
243 );
244 }
245 sig
246}
247
248#[must_use]
249pub fn verify_detached_signature(
250 sig: &DetachedSignature,
251 msg: &[u8],
252 pk: &PublicKey,
253) -> std::result::Result<(), primitive::VerificationError> {
254 verify_detached_signature_portable(sig, msg, pk)
255}
256
257fn verify_detached_signature_portable(
258 sig: &DetachedSignature,
259 msg: &[u8],
260 pk: &PublicKey,
261) -> std::result::Result<(), primitive::VerificationError> {
262 let res = unsafe {
263 ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_verify(
264 sig.0.as_ptr(),
265 sig.1,
266 msg.as_ptr(),
267 msg.len(),
268 pk.0.as_ptr(),
269 )
270 };
271 match res {
272 0 => Ok(()),
273 -1 => Err(primitive::VerificationError::InvalidSignature),
274 _ => Err(primitive::VerificationError::UnknownVerificationError),
275 }
276}
277
278#[cfg(test)]
279mod test {
280 use super::*;
281 use rand::prelude::*;
282
283 #[test]
284 pub fn test_sign() {
285 let mut rng = rand::thread_rng();
286 let len: u16 = rng.gen();
287
288 let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
289 let (pk, sk) = keypair();
290 let sm = sign(&message, &sk);
291 let verifiedmsg = open(&sm, &pk).unwrap();
292 assert!(verifiedmsg == message);
293 }
294
295 #[test]
296 pub fn test_sign_detached() {
297 let mut rng = rand::thread_rng();
298 let len: u16 = rng.gen();
299 let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
300
301 let (pk, sk) = keypair();
302 let sig = detached_sign(&message, &sk);
303 assert!(verify_detached_signature(&sig, &message, &pk).is_ok());
304 assert!(!verify_detached_signature(&sig, &message[..message.len() - 1], &pk).is_ok());
305 }
306}