hbs_lms/hss/
mod.rs

1pub mod aux;
2pub mod definitions;
3pub mod parameter;
4pub mod reference_impl_private_key;
5mod seed_derive;
6pub mod signing;
7pub mod verify;
8
9use core::{convert::TryFrom, marker::PhantomData};
10use tinyvec::ArrayVec;
11
12use crate::{
13    constants::{MAX_HSS_PUBLIC_KEY_LENGTH, REF_IMPL_MAX_PRIVATE_KEY_SIZE},
14    hss::{aux::hss_is_aux_data_used, reference_impl_private_key::Seed},
15    signature::{Error, SignerMut, Verifier},
16    HashChain, Signature, VerifierSignature,
17};
18
19use self::{
20    definitions::{HssPrivateKey, HssPublicKey, InMemoryHssPublicKey},
21    parameter::HssParameter,
22    reference_impl_private_key::ReferenceImplPrivateKey,
23    signing::{HssSignature, InMemoryHssSignature},
24};
25
26/**
27 * Implementation of [`SignerMut`] using [`Signature`].
28 */
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub struct SigningKey<H: HashChain> {
31    pub bytes: ArrayVec<[u8; REF_IMPL_MAX_PRIVATE_KEY_SIZE]>,
32    phantom_data: PhantomData<H>,
33}
34
35impl<H: HashChain> SigningKey<H> {
36    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
37        let bytes = ArrayVec::try_from(bytes).map_err(|_| Error::new())?;
38
39        Ok(Self {
40            bytes,
41            phantom_data: PhantomData,
42        })
43    }
44
45    pub fn as_slice(&self) -> &[u8] {
46        self.bytes.as_slice()
47    }
48
49    pub fn as_mut_slice(&mut self) -> &mut [u8] {
50        self.bytes.as_mut_slice()
51    }
52
53    pub fn get_lifetime(&self) -> Result<u64, Error> {
54        let rfc_sk = ReferenceImplPrivateKey::from_binary_representation(self.bytes.as_slice())
55            .map_err(|_| Error::new())?;
56
57        let parsed_sk = HssPrivateKey::<H>::from(&rfc_sk, &mut None).map_err(|_| Error::new())?;
58
59        Ok(parsed_sk.get_lifetime())
60    }
61
62    pub fn try_sign_with_aux(
63        &mut self,
64        msg: &[u8],
65        aux_data: Option<&mut &mut [u8]>,
66    ) -> Result<Signature, Error> {
67        let private_key = self.bytes;
68        let mut private_key_update_function = |new_key: &[u8]| {
69            self.bytes.as_mut_slice().copy_from_slice(new_key);
70            Ok(())
71        };
72
73        hss_sign::<H>(
74            msg,
75            private_key.as_slice(),
76            &mut private_key_update_function,
77            aux_data,
78        )
79    }
80}
81
82impl<H: HashChain> SignerMut<Signature> for SigningKey<H> {
83    fn try_sign(&mut self, msg: &[u8]) -> Result<Signature, Error> {
84        self.try_sign_with_aux(msg, None)
85    }
86}
87
88/**
89 * Implementation of [`Verifier`] using [`Signature`] or [`VerifierSignature`].
90 */
91#[derive(Clone, Debug, PartialEq, Eq)]
92pub struct VerifyingKey<H: HashChain> {
93    pub bytes: ArrayVec<[u8; MAX_HSS_PUBLIC_KEY_LENGTH]>,
94    phantom_data: PhantomData<H>,
95}
96
97impl<H: HashChain> VerifyingKey<H> {
98    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
99        let bytes = ArrayVec::try_from(bytes).map_err(|_| Error::new())?;
100
101        Ok(Self {
102            bytes,
103            phantom_data: PhantomData,
104        })
105    }
106
107    pub fn as_slice(&self) -> &[u8] {
108        self.bytes.as_slice()
109    }
110}
111
112impl<H: HashChain> Verifier<Signature> for VerifyingKey<H> {
113    fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
114        hss_verify::<H>(msg, signature.as_ref(), &self.bytes)
115    }
116}
117
118impl<'a, H: HashChain> Verifier<VerifierSignature<'a>> for VerifyingKey<H> {
119    fn verify(&self, msg: &[u8], signature: &VerifierSignature) -> Result<(), Error> {
120        hss_verify::<H>(msg, signature.as_ref(), &self.bytes)
121    }
122}
123
124/**
125 * Verify a signature ([`Signature`] or [`VerifierSignature`]).
126 *
127 * # Arguments
128 * * `HashChain` - The hasher implementation that should be used. ```Sha256``` is a standard software implementation.
129 * * `message` - The message that should be verified.
130 * * `signature` - The signature that should be used for verification.
131 * * `public_key` - The public key that should be used for verification.
132 */
133pub fn hss_verify<H: HashChain>(
134    message: &[u8],
135    signature: &[u8],
136    public_key: &[u8],
137) -> Result<(), Error> {
138    let signature = InMemoryHssSignature::<H>::new(signature).ok_or_else(Error::new)?;
139    let public_key = InMemoryHssPublicKey::<H>::new(public_key).ok_or_else(Error::new)?;
140
141    crate::hss::verify::verify(&signature, &public_key, message).map_err(|_| Error::new())
142}
143
144/**
145 * Generate a [`Signature`].
146 *
147 * # Arguments
148 * * `HashChain` - The hasher implementation that should be used. ```Sha256``` is a standard software implementation.
149 * * `message` - The message that should be signed.
150 * * `private_key` - The private key that should be used.
151 * * `private_key_update_function` - The update function that is called with the new private key. This function should save the new private key.
152 * * `aux_data` - Auxiliary data to speedup signature generation if available
153 */
154
155pub fn hss_sign<H: HashChain>(
156    message: &[u8],
157    private_key: &[u8],
158    private_key_update_function: &mut dyn FnMut(&[u8]) -> Result<(), ()>,
159    aux_data: Option<&mut &mut [u8]>,
160) -> Result<Signature, Error> {
161    hss_sign_core::<H>(
162        Some(message),
163        None,
164        private_key,
165        private_key_update_function,
166        aux_data,
167    )
168}
169
170#[cfg(feature = "fast_verify")]
171pub fn hss_sign_mut<H: HashChain>(
172    message_mut: &mut [u8],
173    private_key: &[u8],
174    private_key_update_function: &mut dyn FnMut(&[u8]) -> Result<(), ()>,
175    aux_data: Option<&mut &mut [u8]>,
176) -> Result<Signature, Error> {
177    if message_mut.len() <= H::OUTPUT_SIZE.into() {
178        return Err(Error::new());
179    }
180
181    let (_, message_randomizer) = message_mut.split_at(message_mut.len() - H::OUTPUT_SIZE as usize);
182    if !message_randomizer.iter().all(|&byte| byte == 0u8) {
183        return Err(Error::new());
184    }
185
186    hss_sign_core::<H>(
187        None,
188        Some(message_mut),
189        private_key,
190        private_key_update_function,
191        aux_data,
192    )
193}
194
195fn hss_sign_core<H: HashChain>(
196    message: Option<&[u8]>,
197    message_mut: Option<&mut [u8]>,
198    private_key: &[u8],
199    private_key_update_function: &mut dyn FnMut(&[u8]) -> Result<(), ()>,
200    aux_data: Option<&mut &mut [u8]>,
201) -> Result<Signature, Error> {
202    let mut rfc_private_key = ReferenceImplPrivateKey::from_binary_representation(private_key)
203        .map_err(|_| Error::new())?;
204
205    let is_aux_data_used = if let Some(ref aux_data) = aux_data {
206        hss_is_aux_data_used(aux_data)
207    } else {
208        false
209    };
210
211    let parameters = rfc_private_key
212        .compressed_parameter
213        .to::<H>()
214        .map_err(|_| Error::new())?;
215    let mut expanded_aux_data = HssPrivateKey::get_expanded_aux_data(
216        aux_data,
217        &rfc_private_key,
218        parameters[0].get_lms_parameter(),
219        is_aux_data_used,
220    );
221
222    let mut private_key = HssPrivateKey::<H>::from(&rfc_private_key, &mut expanded_aux_data)
223        .map_err(|_| Error::new())?;
224
225    let hss_signature = HssSignature::sign(
226        &mut private_key,
227        message,
228        message_mut,
229        &mut expanded_aux_data,
230    )
231    .map_err(|_| Error::new())?;
232
233    // Advance private key
234    rfc_private_key.increment(&private_key);
235    private_key_update_function(&rfc_private_key.to_binary_representation())
236        .map_err(|_| Error::new())?;
237
238    let hash_iterations = {
239        let mut hash_iterations: u32 = 0;
240        for signed_public_key in hss_signature.signed_public_keys.iter() {
241            hash_iterations += signed_public_key.sig.lmots_signature.hash_iterations as u32;
242        }
243        hash_iterations + hss_signature.signature.lmots_signature.hash_iterations as u32
244    };
245
246    Signature::from_bytes_verbose(&hss_signature.to_binary_representation(), hash_iterations)
247}
248
249/**
250 * Generate [`SigningKey`] and [`VerifyingKey`].
251 * # Arguments
252 *
253 * * `HashChain` - The hasher implementation that should be used. ```Sha256``` is a standard software implementation.
254 * * `parameters` - An array which specifies the Winternitz parameter and tree height of each individual HSS level. The first element describes Level 1, the second element Level 2 and so on.
255 * * `seed` - An optional seed which will be used to generate the private key. It must be only used for testing purposes and not for production used key pairs.
256 * * `aux_data` - The reference to a slice to auxiliary data. This can be used to speedup signature generation.
257 *
258 * # Example
259 * ```
260 * use rand::{rngs::OsRng, RngCore};
261 * use tinyvec::ArrayVec;
262 * use hbs_lms::{keygen, HssParameter, LmotsAlgorithm, LmsAlgorithm, Sha256_256, HashChain, Seed};
263 *
264 * let parameters = [
265 *      HssParameter::new(LmotsAlgorithm::LmotsW4, LmsAlgorithm::LmsH5),
266 *      HssParameter::new(LmotsAlgorithm::LmotsW1, LmsAlgorithm::LmsH5),
267 * ];
268 * let mut aux_data = vec![0u8; 10_000];
269 * let aux_slice: &mut &mut [u8] = &mut &mut aux_data[..];
270 * let mut seed = Seed::default();
271 * OsRng.fill_bytes(seed.as_mut_slice());
272 *
273 * let (signing_key, verifying_key) =
274 *      keygen::<Sha256_256>(&parameters, &seed, Some(aux_slice)).unwrap();
275 * ```
276 */
277pub fn hss_keygen<H: HashChain>(
278    parameters: &[HssParameter<H>],
279    seed: &Seed<H>,
280    aux_data: Option<&mut &mut [u8]>,
281) -> Result<(SigningKey<H>, VerifyingKey<H>), Error> {
282    let private_key =
283        ReferenceImplPrivateKey::generate(parameters, seed).map_err(|_| Error::new())?;
284
285    let hss_public_key = HssPublicKey::from(&private_key, aux_data).map_err(|_| Error::new())?;
286
287    let signing_key = SigningKey::from_bytes(&private_key.to_binary_representation())?;
288    let verifying_key = VerifyingKey::from_bytes(&hss_public_key.to_binary_representation())?;
289    Ok((signing_key, verifying_key))
290}
291
292#[cfg(test)]
293mod tests {
294    use crate::util::helper::test_helper::gen_random_seed;
295    use crate::{
296        constants::{LMS_LEAF_IDENTIFIERS_SIZE, MAX_HASH_SIZE},
297        hasher::{
298            sha256::{Sha256_128, Sha256_192, Sha256_256},
299            shake256::{Shake256_128, Shake256_192, Shake256_256},
300            HashChain,
301        },
302        LmotsAlgorithm, LmsAlgorithm,
303    };
304
305    use super::*;
306
307    #[test]
308    fn update_keypair() {
309        let message = [
310            32u8, 48, 2, 1, 48, 58, 20, 57, 9, 83, 99, 255, 0, 34, 2, 1, 0,
311        ];
312        type H = Sha256_256;
313        let seed = gen_random_seed::<H>();
314
315        let lmots = LmotsAlgorithm::LmotsW4;
316        let lms = LmsAlgorithm::LmsH5;
317        let parameters = [HssParameter::new(lmots, lms)];
318
319        let (mut signing_key, verifying_key) =
320            hss_keygen::<H>(&parameters, &seed, None).expect("Should generate HSS keys");
321
322        let signing_key_const = signing_key.clone();
323
324        let mut update_private_key = |new_key: &[u8]| {
325            signing_key.as_mut_slice().copy_from_slice(new_key);
326            Ok(())
327        };
328
329        let signature = hss_sign::<H>(
330            &message,
331            signing_key_const.as_slice(),
332            &mut update_private_key,
333            None,
334        )
335        .expect("Signing should complete without error.");
336
337        assert!(hss_verify::<H>(&message, signature.as_ref(), verifying_key.as_slice()).is_ok());
338
339        assert_ne!(signing_key.as_slice(), signing_key_const.as_slice());
340        assert_eq!(
341            signing_key.as_slice()[LMS_LEAF_IDENTIFIERS_SIZE..],
342            signing_key_const.as_slice()[LMS_LEAF_IDENTIFIERS_SIZE..]
343        );
344    }
345
346    #[test]
347    fn exhaust_keypair() {
348        let message = [
349            32u8, 48, 2, 1, 48, 58, 20, 57, 9, 83, 99, 255, 0, 34, 2, 1, 0,
350        ];
351        type H = Sha256_256;
352        let seed = gen_random_seed::<H>();
353
354        let lmots = LmotsAlgorithm::LmotsW2;
355        let lms = LmsAlgorithm::LmsH2;
356        let parameters = [HssParameter::new(lmots, lms), HssParameter::new(lmots, lms)];
357
358        let (mut signing_key, verifying_key) =
359            hss_keygen::<H>(&parameters, &seed, None).expect("Should generate HSS keys");
360        let keypair_lifetime = signing_key.get_lifetime().unwrap();
361
362        assert_ne!(
363            signing_key.as_slice()[(REF_IMPL_MAX_PRIVATE_KEY_SIZE - H::OUTPUT_SIZE as usize)..],
364            [0u8; H::OUTPUT_SIZE as usize],
365        );
366
367        for index in 0..keypair_lifetime {
368            assert_eq!(
369                signing_key.as_slice()[..LMS_LEAF_IDENTIFIERS_SIZE],
370                index.to_be_bytes(),
371            );
372            assert_eq!(
373                keypair_lifetime - signing_key.get_lifetime().unwrap(),
374                index
375            );
376
377            let signing_key_const = signing_key.clone();
378
379            let mut update_private_key = |new_key: &[u8]| {
380                signing_key.as_mut_slice().copy_from_slice(new_key);
381                Ok(())
382            };
383
384            let signature = hss_sign::<H>(
385                &message,
386                signing_key_const.as_slice(),
387                &mut update_private_key,
388                None,
389            )
390            .expect("Signing should complete without error.");
391
392            assert!(
393                hss_verify::<H>(&message, signature.as_ref(), verifying_key.as_slice()).is_ok()
394            );
395        }
396        assert_eq!(
397            signing_key.as_slice()[(REF_IMPL_MAX_PRIVATE_KEY_SIZE - H::OUTPUT_SIZE as usize)..],
398            [0u8; H::OUTPUT_SIZE as usize],
399        );
400    }
401
402    #[test]
403    #[should_panic(expected = "Signing should panic!")]
404    fn use_exhausted_keypair() {
405        let message = [
406            32u8, 48, 2, 1, 48, 58, 20, 57, 9, 83, 99, 255, 0, 34, 2, 1, 0,
407        ];
408        type H = Sha256_256;
409        let seed = gen_random_seed::<H>();
410
411        let lmots = LmotsAlgorithm::LmotsW2;
412        let lms = LmsAlgorithm::LmsH2;
413        let parameters = [HssParameter::new(lmots, lms), HssParameter::new(lmots, lms)];
414
415        let (mut signing_key, verifying_key) =
416            hss_keygen::<H>(&parameters, &seed, None).expect("Should generate HSS keys");
417        let keypair_lifetime = signing_key.get_lifetime().unwrap();
418
419        for index in 0..(1u64 + keypair_lifetime) {
420            let signing_key_const = signing_key.clone();
421
422            let mut update_private_key = |new_key: &[u8]| {
423                signing_key.as_mut_slice().copy_from_slice(new_key);
424                Ok(())
425            };
426
427            let signature = hss_sign::<H>(
428                &message,
429                signing_key_const.as_slice(),
430                &mut update_private_key,
431                None,
432            )
433            .unwrap_or_else(|_| {
434                if index < keypair_lifetime {
435                    panic!("Signing should complete without error.");
436                } else {
437                    assert!(signing_key.get_lifetime().is_err());
438                    panic!("Signing should panic!");
439                }
440            });
441
442            assert!(
443                hss_verify::<H>(&message, signature.as_ref(), verifying_key.as_slice()).is_ok()
444            );
445        }
446    }
447
448    #[test]
449    fn keygen_with_forged_aux_data() {
450        type H = Sha256_256;
451        let seed = gen_random_seed::<H>();
452
453        let lmots = LmotsAlgorithm::LmotsW2;
454        let lms = LmsAlgorithm::LmsH5;
455        let parameters = [HssParameter::new(lmots, lms), HssParameter::new(lmots, lms)];
456
457        let mut aux_data = [0u8; 1_000];
458        let aux_slice: &mut &mut [u8] = &mut &mut aux_data[..];
459
460        let (sk1, vk1) =
461            hss_keygen::<H>(&parameters, &seed, Some(aux_slice)).expect("Should generate HSS keys");
462
463        aux_slice[2 * MAX_HASH_SIZE - 1] ^= 0x1;
464
465        let (sk2, vk2) =
466            hss_keygen::<H>(&parameters, &seed, Some(aux_slice)).expect("Should generate HSS keys");
467
468        assert_eq!(sk1, sk2);
469        assert_eq!(vk1, vk2);
470    }
471
472    #[test]
473    fn test_signing_sha256_128() {
474        test_signing_core::<Sha256_128>();
475    }
476
477    #[test]
478    fn test_signing_sha256_192() {
479        test_signing_core::<Sha256_192>();
480    }
481
482    #[test]
483    fn test_signing_sha256_256() {
484        test_signing_core::<Sha256_256>();
485    }
486
487    #[test]
488    fn test_signing_shake256_128() {
489        test_signing_core::<Shake256_128>();
490    }
491
492    #[test]
493    fn test_signing_shake256_192() {
494        test_signing_core::<Shake256_192>();
495    }
496
497    #[test]
498    fn test_signing_shake256_256() {
499        test_signing_core::<Shake256_256>();
500    }
501
502    fn test_signing_core<H: HashChain>() {
503        let seed = gen_random_seed::<H>();
504        let (mut signing_key, verifying_key) = hss_keygen::<H>(
505            &[
506                HssParameter::construct_default_parameters(),
507                HssParameter::construct_default_parameters(),
508                HssParameter::construct_default_parameters(),
509            ],
510            &seed,
511            None,
512        )
513        .expect("Should generate HSS keys");
514
515        let message_values = [
516            32u8, 48, 2, 1, 48, 58, 20, 57, 9, 83, 99, 255, 0, 34, 2, 1, 0,
517        ];
518        let mut message = [0u8; 64];
519        message[..message_values.len()].copy_from_slice(&message_values);
520
521        let signing_key_const = signing_key.clone();
522
523        let mut update_private_key = |new_key: &[u8]| {
524            signing_key.as_mut_slice().copy_from_slice(new_key);
525            Ok(())
526        };
527
528        let signature = hss_sign::<H>(
529            &message,
530            signing_key_const.as_slice(),
531            &mut update_private_key,
532            None,
533        )
534        .expect("Signing should complete without error.");
535
536        assert!(hss_verify::<H>(&message, signature.as_ref(), verifying_key.as_slice(),).is_ok());
537
538        message[0] = 33;
539
540        assert!(hss_verify::<H>(&message, signature.as_ref(), verifying_key.as_slice(),).is_err());
541    }
542
543    #[cfg(feature = "fast_verify")]
544    #[test]
545    fn test_signing_fast_verify() {
546        type H = Sha256_256;
547        let seed = gen_random_seed::<H>();
548
549        let (mut signing_key, verifying_key) = hss_keygen::<H>(
550            &[
551                HssParameter::construct_default_parameters(),
552                HssParameter::construct_default_parameters(),
553                HssParameter::construct_default_parameters(),
554            ],
555            &seed,
556            None,
557        )
558        .expect("Should generate HSS keys");
559
560        let message_values = [
561            32u8, 48, 2, 1, 48, 58, 20, 57, 9, 83, 99, 255, 0, 34, 2, 1, 0,
562        ];
563        let mut message = [0u8; 64];
564        message[..message_values.len()].copy_from_slice(&message_values);
565
566        let signing_key_const = signing_key.clone();
567
568        let mut update_private_key = |new_key: &[u8]| {
569            signing_key.as_mut_slice().copy_from_slice(new_key);
570            Ok(())
571        };
572
573        let signature = hss_sign_mut::<H>(
574            &mut message,
575            signing_key_const.as_slice(),
576            &mut update_private_key,
577            None,
578        )
579        .expect("Signing should complete without error.");
580
581        assert!(H::OUTPUT_SIZE == MAX_HASH_SIZE as u16);
582        assert_ne!(
583            message[(message.len() - MAX_HASH_SIZE)..],
584            [0u8; MAX_HASH_SIZE]
585        );
586
587        assert!(hss_verify::<H>(&message, signature.as_ref(), verifying_key.as_slice()).is_ok());
588    }
589}