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
//! Provides [`Scalar`] and related types.
//!
//! In elliptic curve cryptography scalars are non-point values that can be used to multiply
//! points. The most common type of scalars are private keys. However not all scalars are private
//! keys. They can even be public *values*. To make handling them safer and easier this module
//! provides the `Scalar` type and related.
use core::fmt;
/// Positive 256-bit integer guaranteed to be less than the secp256k1 curve order.
///
/// The difference between `PrivateKey` and `Scalar` is that `Scalar` doesn't guarantee being
/// securely usable as a private key.
///
/// **Warning: the operations on this type are NOT constant time!**
/// Using this with secret values is not advised.
// Internal represenation is big endian to match what `libsecp256k1` uses.
// Also easier to implement comparison.
// Debug impl omitted for now, the bytes may be secret
#[allow(missing_debug_implementations)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Scalar([u8; 32]);
const MAX_RAW: [u8; 32] = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40
];
impl Scalar {
/// Scalar representing `0`
pub const ZERO: Scalar = Scalar([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
/// Scalar representing `1`
pub const ONE: Scalar = Scalar([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
/// Maximum valid value: `curve_order - 1`
pub const MAX: Scalar = Scalar(MAX_RAW);
/// Generates a random scalar
#[cfg(any(test, feature = "rand-std"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
pub fn random() -> Self {
Self::random_custom(rand::thread_rng())
}
/// Generates a random scalar using supplied RNG
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn random_custom<R: rand::Rng>(mut rng: R) -> Self {
let mut bytes = [0u8; 32];
loop {
rng.fill_bytes(&mut bytes);
// unlikely to go past MAX
if let Ok(scalar) = Scalar::from_be_bytes(bytes) {
break scalar;
}
}
}
/// Tries to deserialize from big endian bytes
///
/// **Security warning:** this function is not constant time!
/// Passing secret data is not recommended.
///
/// # Errors
///
/// Returns error when the value is above the curve order.
pub fn from_be_bytes(value: [u8; 32]) -> Result<Self, OutOfRangeError> {
// Lexicographic ordering of arrays of the same length is same as ordering of BE numbers
if value <= MAX_RAW {
Ok(Scalar(value))
} else {
Err(OutOfRangeError {})
}
}
/// Tries to deserialize from little endian bytes
///
/// **Security warning:** this function is not constant time!
/// Passing secret data is not recommended.
///
/// # Errors
///
/// Returns error when the value is above the curve order.
pub fn from_le_bytes(mut value: [u8; 32]) -> Result<Self, OutOfRangeError> {
value.reverse();
Self::from_be_bytes(value)
}
/// Serializes to big endian bytes
pub fn to_be_bytes(self) -> [u8; 32] {
self.0
}
/// Serializes to little endian bytes
pub fn to_le_bytes(self) -> [u8; 32] {
let mut res = self.0;
res.reverse();
res
}
// returns a reference to internal bytes
// non-public to not leak the internal representation
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] {
&self.0
}
pub(crate) fn as_c_ptr(&self) -> *const u8 {
use secp256k1_sys::CPtr;
self.as_be_bytes().as_c_ptr()
}
}
impl From<crate::SecretKey> for Scalar {
fn from(value: crate::SecretKey) -> Self {
Scalar(value.secret_bytes())
}
}
/// Error returned when the value of scalar is invalid - larger than the curve order.
// Intentionally doesn't implement `Copy` to improve forward compatibility.
// Same reason for `non_exhaustive`.
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[non_exhaustive]
pub struct OutOfRangeError {
}
impl fmt::Display for OutOfRangeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt("the value is not a member of secp256k1 field", f)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for OutOfRangeError {}