Module curve25519_dalek::scalar
source · Expand description
Arithmetic on scalars (integers mod the group order).
Both the Ristretto group and the Ed25519 basepoint have prime order \( \ell = 2^{252} + 27742317777372353535851937790883648493 \).
This code is intended to be useful with both the Ristretto group (where everything is done modulo \( \ell \)), and the X/Ed25519 setting, which mandates specific bit-twiddles that are not well-defined modulo \( \ell \).
All arithmetic on Scalars
is done modulo \( \ell \).
Constructing a scalar
To create a Scalar
from a supposedly canonical encoding, use
Scalar::from_canonical_bytes
.
This function does input validation, ensuring that the input bytes
are the canonical encoding of a Scalar
.
If they are, we’ll get
Some(Scalar)
in return:
use curve25519_dalek::scalar::Scalar;
let one_as_bytes: [u8; 32] = Scalar::one().to_bytes();
let a: Option<Scalar> = Scalar::from_canonical_bytes(one_as_bytes);
assert!(a.is_some());
However, if we give it bytes representing a scalar larger than \( \ell \)
(in this case, \( \ell + 2 \)), we’ll get None
back:
use curve25519_dalek::scalar::Scalar;
let l_plus_two_bytes: [u8; 32] = [
0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
];
let a: Option<Scalar> = Scalar::from_canonical_bytes(l_plus_two_bytes);
assert!(a.is_none());
Another way to create a Scalar
is by reducing a \(256\)-bit integer mod
\( \ell \), for which one may use the
Scalar::from_bytes_mod_order
method. In the case of the second example above, this would reduce the
resultant scalar \( \mod \ell \), producing \( 2 \):
use curve25519_dalek::scalar::Scalar;
let l_plus_two_bytes: [u8; 32] = [
0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
];
let a: Scalar = Scalar::from_bytes_mod_order(l_plus_two_bytes);
let two: Scalar = Scalar::one() + Scalar::one();
assert!(a == two);
There is also a constructor that reduces a \(512\)-bit integer,
Scalar::from_bytes_mod_order_wide
.
To construct a Scalar
as the hash of some input data, use
Scalar::hash_from_bytes
,
which takes a buffer, or
Scalar::from_hash
,
which allows an IUF API.
use sha2::{Digest, Sha512};
use curve25519_dalek::scalar::Scalar;
// Hashing a single byte slice
let a = Scalar::hash_from_bytes::<Sha512>(b"Abolish ICE");
// Streaming data into a hash object
let mut hasher = Sha512::default();
hasher.update(b"Abolish ");
hasher.update(b"ICE");
let a2 = Scalar::from_hash(hasher);
assert_eq!(a, a2);
Finally, to create a Scalar
with a specific bit-pattern
(e.g., for compatibility with X/Ed25519
“clamping”),
use Scalar::from_bits
. This
constructs a scalar with exactly the bit pattern given, without any
assurances as to reduction modulo the group order:
use curve25519_dalek::scalar::Scalar;
let l_plus_two_bytes: [u8; 32] = [
0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
];
let a: Scalar = Scalar::from_bits(l_plus_two_bytes);
let two: Scalar = Scalar::one() + Scalar::one();
assert!(a != two); // the scalar is not reduced (mod l)…
assert!(! a.is_canonical()); // …and therefore is not canonical.
assert!(a.reduce() == two); // if we were to reduce it manually, it would be.
The resulting Scalar
has exactly the specified bit pattern,
except for the highest bit, which will be set to 0.
Structs
Scalar
struct holds an integer \(s < 2^{255} \) which
represents an element of \(\mathbb Z / \ell\).