crrl/
lib.rs

1//! Crrl is a Rust library for cryptographic research.
2//!
3//! This library implements computations in some finite fields and
4//! elliptic curves. It aims at providing efficient and secure
5//! (constant-time) implementations, but with portable code, and with a
6//! convenient API so that scalars, curve points, and other field
7//! elements may be used in straightforward expressions with normal
8//! arihtmetic operators.
9//!
10//! Finite fields are implemented through some customizable types defined
11//! in `backend` (a 32-bit and a 64-bit backends are provided, the "right
12//! one" is automatically selected, unless overridden by a compile-time
13//! feature). The types may support several distinct moduli, chosen
14//! through compile-time type parameter.
15//!
16//! Curve edwards25519 is implemented in the `ed25519` module. The
17//! specialized X25519 function is in `x25519`. The prime-order group
18//! ristretto255 (internally based on edwards25519) is defined in the
19//! `ristretto255` module. NIST curve P-256 (aka "secp256r1" and
20//! "prime256v1") is implemented in the `p256` module (with the ECDSA
21//! signature algorithm). Double-odd curves jq255e and jq255s are
22//! implemented by `jq255e` and `jq255s`, respectively (including
23//! signature and key exchange schemes). Secp256k1 is implemented in
24//! `secp256k1`. Edwards448 is in `ed448`, while the specialized X448
25//! function is in `x448`. The prime-order decaf448 group is implemented
26//! in `decaf448`.
27//!
28//! # Usage
29//!
30//! The library is "mostly `no_std`". By default, it compiles against the
31//! standard library. It can be compiled in `no_std` mode, in which case
32//! all functionality is still available, except verification of truncated
33//! ECDSA signatures with curve P-256.
34//!
35//! # Conventions
36//!
37//! All implemented functions should be strictly constant-time, unless
38//! explicitly documented otherwise (non-constant-time functions normally
39//! have "vartime" in their name). In order to avoid unwanted side-channel
40//! leaks, Booleans are avoided (compilers tend to "optimize" things a bit
41//! too eagerly when handling `bool` values). All functions that return or
42//! use a potentially secret Boolean value use the `u32` type; the convention
43//! is that 0xFFFFFFFF means "true", and 0x00000000 means "false". No other
44//! value shall be used, for they would lead to unpredictable results.
45//! Similarly, the `Eq` or `PartialEq` traits are not implemented.
46//!
47//! Algebraic operations on field elements and curve points are performed
48//! with the usual operators (e.g. `+`); appropriate traits are defined
49//! so that structure types and pointers to structure types can be used
50//! more or less interchangeably. Throughout the code, functions that
51//! modify the object on which they are called tend to have a name in
52//! `set_*()` (e.g. for a curve point `P`, if we want to compute the
53//! double of that point, then `P.set_double()` modifies the point
54//! structure in place, while `P.double()` leaves `P` unmodified and
55//! returns the double as a new structure instance).
56//!
57//! # Truncated Signatures
58//!
59//! Apart from standard support for curve operations and signature
60//! algorithms, _truncated signatures_ are implemented for both Ed25519
61//! (Schnorr signatures over edwards25519) and ECDSA (over P-256). A
62//! truncated signature is a shrunk version, by up to 32 bits, of a
63//! normal signature; the verification process is then more expensive,
64//! though not necessarily intolerably expensive, depending on usage
65//! context (the most expensive verification function is for ECDSA on
66//! P-256, with maximal 32-bit truncation; in that case, verification
67//! cost can be up to about 0.65 seconds on a 500 MHz ARM Cortex A53; but
68//! Ed25519 signatures with 32-bit truncation can be verified in less
69//! than 0.05 seconds on the same hardware). Signature truncation can be
70//! useful in situations with strong I/O constraints, where every data
71//! bit counts, but where use of fully standard Ed25519 or ECDSA
72//! signature generators is made mandatory because of some regulatory or
73//! physical constraints of the signing hardware.
74//! 
75//! # Performance
76//!
77//! On an Intel i5-8259U CPU (Coffee Lake core), Ed25519 signatures have
78//! been benchmarked at about 51600 cycles for signing, 111000 cycles for
79//! verification; these are not bad values, and are competitive or at
80//! least within 30% of performance obtained from assembly-optimized
81//! implementations on the same hardware. For P-256, signing time is
82//! about 125000 cycles, verification is 256000 cycles. For the jq255e
83//! curve, signatures are generated in about 54700 cycles, and verified
84//! in only 82800 cycles (56200 and 86800, respectively, for jq255s).
85//! These figures have been obtained by compiling with Rust 1.59 in
86//! release mode, with the flags `-C target-cpu=native`.
87//!
88//! On an ARM Cortex A53 (RaspberryPi Model 3B), Ed25519 signing was
89//! measured at 213000 cycles, verification at 479000 cycles; for P-256,
90//! the figures were 389000 and 991000, respectively. With jq255e,
91//! signature generation and verification use 241000 and 358000 cycles,
92//! respectively (248000 and 369000 for jq255s).
93//!
94//! No inline assembly is used. On x86-64 architectures, the
95//! `_addcarry_u64()` and `_subborrow_u64()` intrinsics are used
96//! (from `core::arch::x86_64`); however, plain implementations with
97//! no intrinsics are available (and used on, for instance, aarch64).
98
99#![no_std]
100
101#[cfg(all(feature = "alloc", not(feature = "std")))]
102#[macro_use]
103#[allow(unused_imports)]
104extern crate alloc;
105
106#[cfg(feature = "std")]
107#[macro_use]
108#[allow(unused_imports)]
109extern crate std;
110
111#[cfg(all(feature = "alloc", not(feature = "std")))]
112#[allow(unused_imports)]
113pub(crate) use alloc::vec::Vec;
114
115#[cfg(feature = "std")]
116#[allow(unused_imports)]
117pub(crate) use std::vec::Vec;
118
119/// The `rand_core` types are re-exported so that users of crrl do not
120/// have to worry about using the exact correct version of `rand_core`.
121pub use rand_core::{CryptoRng, RngCore, Error as RngError};
122
123#[allow(unused_macros)]
124macro_rules! static_assert {
125    ($condition:expr) => {
126        let _ = &[()][1 - ($condition) as usize];
127    }
128}
129
130pub mod backend;
131pub mod field;
132
133pub use backend::{Zu128, Zu256, Zu384};
134
135#[cfg(feature = "ed25519")]
136pub mod ed25519;
137
138#[cfg(feature = "x25519")]
139pub mod x25519;
140
141#[cfg(feature = "ristretto255")]
142pub mod ristretto255;
143
144#[cfg(feature = "jq255e")]
145pub mod jq255e;
146
147#[cfg(feature = "jq255s")]
148pub mod jq255s;
149
150#[cfg(feature = "p256")]
151pub mod p256;
152
153#[cfg(feature = "secp256k1")]
154pub mod secp256k1;
155
156#[cfg(feature = "gls254")]
157pub mod gls254;
158
159#[cfg(feature = "ed448")]
160pub mod ed448;
161
162#[cfg(feature = "x448")]
163pub mod x448;
164
165#[cfg(feature = "decaf448")]
166pub mod decaf448;
167
168#[cfg(all(feature = "alloc", feature = "frost"))]
169pub mod frost;
170
171#[cfg(feature = "lms")]
172pub mod lms;
173
174#[cfg(feature = "blake2s")]
175pub mod blake2s;