libdecaf_ristretto255 (libdecaf v3.0.0)
View SourceRistretto255 prime-order group arithmetic, backed directly by libdecaf_nif.
Implements the group operations and element derivation specified in
RFC 9496.
Points use the canonical 32-byte Ristretto255 encoding. Scalars are
unsigned little-endian integers in exactly 32 bytes, strictly smaller
than the group order l:
l = 2^252 + 27742317777372353535851937790883648493Point and scalar binaries have the same length but different meanings. Use
point_is_valid/1 and scalar_is_canonical/1 to validate untrusted inputs.
The Erlang binary types describe their size; native operations validate their
contents. Arithmetic accepts the identity point and scalar zero, and raises
badarg for invalid operands. scalar_invert/1 returns error for zero.
These encodings are specific to this group; EdDSA and X25519/X448 keys use
different formats and cannot be substituted for group points or scalars.
Use scalar_reduce/1 to encode an integer modulo l, or scalar_random/0
to generate a scalar with negligible reduction bias. Scalars are not clamped.
For example, multiplication by three agrees with repeated point addition:
Three = libdecaf_ristretto255:scalar_reduce(<<3>>),
Base = libdecaf_ristretto255:base(),
Point = libdecaf_ristretto255:base_scalarmul(Three),
Point = libdecaf_ristretto255:point_add(Base, libdecaf_ristretto255:point_double(Base)).point_from_hash/1 consumes exactly 64 bytes of prepared input; it does
not hash a message itself. Use a protocol-defined, domain-separated hash/XOF
construction to derive those bytes. point_from_hash_nonuniform/1 exposes
the single-map operation for protocols that specifically need it.
precompute/1 creates an immutable native multiplication table for reuse with
precomputed_scalarmul/2. Tables belong to this group, can be shared between
processes, and are released automatically when no references remain. Ordinary
operations return canonical binaries and do not mutate their inputs.
Summary
Types
A canonical 32-byte Ristretto255 point encoding, including the identity.
Use point_is_valid/1 to check the encoded contents at runtime.
An immutable native multiplication table for a Ristretto255 point.
Created by precompute/1 and usable only with this group's precomputed_scalarmul/2.
A canonical 32-byte unsigned little-endian integer smaller than l.
Zero is valid. Use scalar_is_canonical/1 to validate an encoding or
scalar_reduce/1 to reduce an integer into this field.
Functions
Return the canonical Ristretto255 generator from RFC 9496.
Multiply the canonical Ristretto255 generator by Scalar.
Return the Ristretto255 identity element, encoded as 32 zero bytes.
Return the canonical encoding of Left + Right.
Return Point + Point in canonical encoding.
Return Scalar1 * Point1 + Scalar2 * Point2 in canonical encoding.
Return whether two encoded points represent the same group element.
Derive a Ristretto255 element from exactly 64 bytes using RFC 9496.
Apply the upstream single map to exactly 32 bytes.
Return whether Point is a valid canonical 32-byte Ristretto255 encoding.
Return the additive inverse of Point in canonical encoding.
Return Scalar * Point in canonical encoding.
Return the canonical encoding of Left - Right.
Build an immutable native multiplication table for Point.
Multiply the point stored in Precomputed by Scalar.
Return (Left + Right) mod l, where l is the group order.
Divide Scalar by two modulo the group order.
Return the multiplicative inverse of Scalar modulo the group order.
Return whether Scalar is a canonical 32-byte little-endian scalar.
Return (Left * Right) mod l, where l is the group order.
Return -Scalar mod l, where l is the group order.
Generate a canonical scalar using crypto:strong_rand_bytes/1.
Reduce an arbitrary-length unsigned little-endian integer modulo the group order.
Return (Left - Right) mod l, where l is the group order.
Types
-type point() :: <<_:256>>.
A canonical 32-byte Ristretto255 point encoding, including the identity.
Use point_is_valid/1 to check the encoded contents at runtime.
-opaque precomputed()
An immutable native multiplication table for a Ristretto255 point.
Created by precompute/1 and usable only with this group's precomputed_scalarmul/2.
-type scalar() :: <<_:256>>.
A canonical 32-byte unsigned little-endian integer smaller than l.
Zero is valid. Use scalar_is_canonical/1 to validate an encoding or
scalar_reduce/1 to reduce an integer into this field.
Functions
-spec base() -> Result when Result :: point().
Return the canonical Ristretto255 generator from RFC 9496.
Use this point for interoperable generator multiplication. The base-scalar multiplication operation uses its built-in precomputed table.
Multiply the canonical Ristretto255 generator by Scalar.
Uses the native library's built-in precomputed generator table.
The scalar must already be canonical; otherwise raises badarg.
One = libdecaf_ristretto255:scalar_reduce(<<1>>),
Base = libdecaf_ristretto255:base(),
Base = libdecaf_ristretto255:base_scalarmul(One).
-spec identity() -> Result when Result :: point().
Return the Ristretto255 identity element, encoded as 32 zero bytes.
Adding this point leaves the other point unchanged. Multiplication by zero and multiplication of the identity by any scalar both return the identity.
Return the canonical encoding of Left + Right.
Both operands must be valid point encodings; otherwise raises badarg.
Adding a point to its negation returns the identity.
Return Point + Point in canonical encoding.
This is equivalent to multiplication by the scalar two.
An invalid point encoding raises badarg.
-spec point_double_scalarmul(Point1, Scalar1, Point2, Scalar2) -> Result when Point1 :: point(), Scalar1 :: scalar(), Point2 :: point(), Scalar2 :: scalar(), Result :: point().
Return Scalar1 * Point1 + Scalar2 * Point2 in canonical encoding.
Computes the same result as two scalar multiplications followed by addition.
Both points must be valid and both scalars canonical; otherwise raises badarg.
Return whether two encoded points represent the same group element.
Both operands are decoded and validated. Invalid encodings raise badarg;
false means that two valid points differ.
Derive a Ristretto255 element from exactly 64 bytes using RFC 9496.
The two halves are mapped separately and their points are added. Uniform
input gives an approximately uniform group element. This operation does
not hash a message: use a protocol-defined, domain-separated hash or XOF
to prepare the input. Wrong-sized binaries and non-binaries raise badarg.
For a random group element, prepare uniformly random input:
UniformBytes = crypto:strong_rand_bytes(64),
Point = libdecaf_ristretto255:point_from_hash(UniformBytes),
true = libdecaf_ristretto255:point_is_valid(Point).
Apply the upstream single map to exactly 32 bytes.
This is one half of the two-map RFC 9496 derivation. Its output has a
different distribution, so use it only when a protocol requires the single
map. Wrong-sized binaries and non-binaries raise badarg.
Return whether Point is a valid canonical 32-byte Ristretto255 encoding.
The identity is valid. Wrong-sized binaries, noncanonical encodings, and
non-binary terms return false instead of raising badarg.
Return the additive inverse of Point in canonical encoding.
The input point and its negation add to the identity.
An invalid point encoding raises badarg.
-spec point_scalarmul(Point, Scalar) -> Result when Point :: point(), Scalar :: scalar(), Result :: point().
Return Scalar * Point in canonical encoding.
The point must be valid and the scalar must already be canonical.
Invalid operands raise badarg; zero and the identity are accepted.
Return the canonical encoding of Left - Right.
Both operands must be valid point encodings; otherwise raises badarg.
Subtracting a point from itself returns the identity.
-spec precompute(Point) -> Result when Point :: point(), Result :: precomputed().
Build an immutable native multiplication table for Point.
Reuse the table when multiplying the same point by many scalars.
The resource can be shared between processes and is released automatically
when no references remain. It is specific to Ristretto255; invalid points raise badarg.
Point = libdecaf_ristretto255:point_double(libdecaf_ristretto255:base()),
Table = libdecaf_ristretto255:precompute(Point),
Scalar = libdecaf_ristretto255:scalar_reduce(<<7>>),
Product = libdecaf_ristretto255:point_scalarmul(Point, Scalar),
Product = libdecaf_ristretto255:precomputed_scalarmul(Table, Scalar).
-spec precomputed_scalarmul(Precomputed, Scalar) -> Result when Precomputed :: precomputed(), Scalar :: scalar(), Result :: point().
Multiply the point stored in Precomputed by Scalar.
The result matches ordinary point-scalar multiplication; the table is unchanged.
A resource from another group, a non-table term, or a noncanonical Ristretto255
scalar raises badarg.
-spec scalar_add(Left, Right) -> Result when Left :: scalar(), Right :: scalar(), Result :: scalar().
Return (Left + Right) mod l, where l is the group order.
Both operands must already be canonical scalars; otherwise raises badarg.
The result is canonically encoded.
Divide Scalar by two modulo the group order.
This is multiplication by the modular inverse of two, rather than integer
division. Adding the result to itself recovers the input, including for odd
scalars. A noncanonical scalar raises badarg.
One = libdecaf_ristretto255:scalar_reduce(<<1>>),
Half = libdecaf_ristretto255:scalar_halve(One),
One = libdecaf_ristretto255:scalar_add(Half, Half).
Return the multiplicative inverse of Scalar modulo the group order.
Multiplying a nonzero scalar by its inverse gives the canonical scalar one.
Zero has no inverse and returns error. Noncanonical scalars raise badarg.
Scalar = libdecaf_ristretto255:scalar_reduce(<<7>>),
Inverse = libdecaf_ristretto255:scalar_invert(Scalar),
One = libdecaf_ristretto255:scalar_reduce(<<1>>),
One = libdecaf_ristretto255:scalar_mul(Scalar, Inverse),
error = libdecaf_ristretto255:scalar_invert(libdecaf_ristretto255:scalar_reduce(<<>>)).
Return whether Scalar is a canonical 32-byte little-endian scalar.
Its integer value must be smaller than the group order; zero is accepted.
Wrong-sized binaries, out-of-range values, and non-binaries return false.
-spec scalar_mul(Left, Right) -> Result when Left :: scalar(), Right :: scalar(), Result :: scalar().
Return (Left * Right) mod l, where l is the group order.
Both operands must already be canonical scalars; otherwise raises badarg.
The result is canonically encoded.
Return -Scalar mod l, where l is the group order.
The result adds to the input to give zero; zero is its own negation.
A noncanonical scalar raises badarg.
-spec scalar_random() -> Scalar when Scalar :: scalar().
Generate a canonical scalar using crypto:strong_rand_bytes/1.
Reduces 64 cryptographically random bytes modulo the group order. The
result has negligible reduction bias and can be zero. Protocols requiring a
nonzero scalar must retry when zero is returned. Random-source failures
propagate from crypto.
Scalar = libdecaf_ristretto255:scalar_random(),
true = libdecaf_ristretto255:scalar_is_canonical(Scalar).
Reduce an arbitrary-length unsigned little-endian integer modulo the group order.
Returns a canonical 32-byte scalar. Leading zero bytes at the
most-significant end are allowed, and the empty binary reduces to zero.
This operation does not hash or clamp its input. Non-binaries raise badarg.
Scalar = libdecaf_ristretto255:scalar_reduce(<<1, 2>>),
513 = binary:decode_unsigned(Scalar, little),
true = libdecaf_ristretto255:scalar_is_canonical(Scalar).
-spec scalar_sub(Left, Right) -> Result when Left :: scalar(), Right :: scalar(), Result :: scalar().
Return (Left - Right) mod l, where l is the group order.
Both operands must already be canonical scalars; otherwise raises badarg.
A negative difference wraps modulo l and the result is canonically encoded.