dilithium_raw/lib.rs
1//! Low level library for post-quantum signature scheme dilithium.
2//!
3//! Uses a slightly modified version of the C code of [`pqclean`] as the actual
4//! implementation, which is compiled by a build script. The API is modified to
5//! put the user in control of required randomness.
6//!
7//! The library has a minimal set of dependencies: in the default configuration
8//! (without [`serde`] support) only [`cty`].
9//!
10//! # Security
11//! __Warning__: This crate is intended as a lower level crate implementing a
12//! primitive and exposing "not hard to misuse" APIs to provide the user with
13//! maximum control. Only use if you know what you are doing! Always read
14//! security sections in the documentation. Otherwise use a higher level
15//! wrapper.
16//!
17//! __Warning__: This crate has not been audited for correctness. The C code is
18//! copied from the well-regarded [`pqclean`] project, but since then
19//! modifications have been made.
20//!
21//! USE AT YOUR OWN RISK!
22//!
23//! # Usage
24//! The API is located in the `dilithiumX` module, for X in {2, 3, 5}. To
25//! generate a keypair, use `generate_keypair`. Note: it requires a buffer
26//! filled with cryptographically secure random bytes. The random buffer is not
27//! modified, so zeroization is left to the user. Example:
28//! ```
29//! use dilithium_raw::dilithium5::generate_keypair;
30//! use rand::rngs::OsRng;
31//! use rand::Rng;
32//! use zeroize::Zeroize;
33//!
34//! // fill buffer of 128 bytes with secure random data
35//! let mut random = [0; 128];
36//! OsRng.fill(&mut random[..]);
37//!
38//! // generate keypair
39//! let (pubkey, seckey) = generate_keypair(&mut random);
40//!
41//! // zeroize the buffer with random data
42//! random.zeroize();
43//! ```
44//!
45//! To sign a message using the secret key, use `sign` and to verify it using
46//! the public key, use `verify`. `verify` returns `Ok` for a valid signature
47//! and `Err` for an invalid signature. Example:
48//! ```
49//! use dilithium_raw::dilithium5::{sign, verify};
50//!
51//! // snip, get a `pubkey` and `seckey` with the public and secret key respectively
52//! # use rand::Rng;
53//! # let mut random = [0; 128];
54//! # rand::rngs::OsRng.fill(&mut random[..]);
55//! # let (pubkey, seckey) = dilithium_raw::dilithium5::generate_keypair(&mut random);
56//!
57//! let msg = "hello world";
58//! let sig = sign(msg, &seckey);
59//! assert!(verify(msg, &sig, &pubkey).is_ok());
60//! ```
61//!
62//! [`cty`]: https://crates.io/crates/cty
63//! [`pqclean`]: https://github.com/PQClean/PQClean
64//! [`serde`]: https://crates.io/crates/serde
65
66#![forbid(rust_2018_compatibility, unsafe_op_in_unsafe_fn)]
67#![deny(future_incompatible, rust_2018_idioms)]
68#![warn(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
69
70/// Low level C bindings.
71pub mod ffi;
72/// Utilities, mostly for use in this crate.
73pub mod util;
74
75/// Message did verify correctly.
76pub struct VerificationOk;
77/// Message did not verify against the given signature.
78pub struct VerificationFailure;
79
80/// Type alias for the return type of verification checks.
81pub type VerificationResult = Result<VerificationOk, VerificationFailure>;
82
83mod sanity {
84 // We need this equality because in the build script we can only get the width
85 // of a pointer, not that of a `usize`.
86 const _: () = core::assert!(core::mem::size_of::<usize>() == core::mem::size_of::<*const u8>());
87}
88
89mod macros;
90
91/// Module containing a mid-level API to dilithium 2.
92#[cfg(feature = "dilithium2")]
93pub mod dilithium2 {
94 use crate::ffi::dilithium2::*;
95 crate::macros::impl_dilithium_module!("regression_tests/dilithium2.ron");
96}
97
98/// Module containing a mid-level API to dilithium 3.
99#[cfg(feature = "dilithium3")]
100pub mod dilithium3 {
101 use crate::ffi::dilithium3::*;
102 crate::macros::impl_dilithium_module!("regression_tests/dilithium3.ron");
103}
104
105/// Module containing a mid-level API to dilithium 5.
106#[cfg(feature = "dilithium5")]
107pub mod dilithium5 {
108 use crate::ffi::dilithium5::*;
109 crate::macros::impl_dilithium_module!("regression_tests/dilithium5.ron");
110}
111
112#[cfg(test)]
113mod tests {
114 #[test]
115 fn it_works() {
116 let result = 2 + 2;
117 assert_eq!(result, 4);
118 }
119}