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

The Scalar struct holds an integer \(s < 2^{255} \) which represents an element of \(\mathbb Z / \ell\).