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