Skip to content

crypto.ed25519.internal.edwards25519 #

README

This module provides arithmetic primitives operations that are useful to implement cryptographic schemes over curve edwards25519, includes:

  1. Arithmetic functions for point addition, doubling, negation, scalar multiplication with an arbitrary point, with the base point, etc.
  2. Arithmetic functions dealing with scalars modulo the prime order L of the base point.

This modules was port of Golang edwards25519 library from edwards25519 to the V language.

About Edwards25519

Twisted Edwards curves are a familly of elliptic curves allowing complete addition formulas without any special case and no point at infinity. Curve edwards25519 is based on prime 2^255 - 19 for efficient implementation. Equation and parameters are given in RFC 7748.

Constants #

const (
	sc_zero = Scalar{
		s: [u8(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]!
	}

	sc_one = Scalar{
		s: [u8(1), 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]!
	}

	sc_minus_one = Scalar{
		s: [u8(236), 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0,
			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16]!
	}
)

fn new_generator_point #

fn new_generator_point() Point

new_generator_point returns a new Point set to the canonical generator.

fn new_identity_point #

fn new_identity_point() Point

new_identity_point returns a new Point set to the identity.

fn new_scalar #

fn new_scalar() Scalar

new_scalar return new zero scalar

fn (Scalar) add #

fn (mut s Scalar) add(x Scalar, y Scalar) Scalar

add sets s = x + y mod l, and returns s.

fn (Scalar) bytes #

fn (mut s Scalar) bytes() []u8

bytes returns the canonical 32-byte little-endian encoding of s.

fn (Scalar) equal #

fn (s Scalar) equal(t Scalar) int

equal returns 1 if s and t are equal, and 0 otherwise.

fn (Scalar) invert #

fn (mut s Scalar) invert(t Scalar) Scalar

invert sets s to the inverse of a nonzero scalar v, and returns s.

If t is zero, invert returns zero.

fn (Scalar) multiply #

fn (mut s Scalar) multiply(x Scalar, y Scalar) Scalar

multiply sets s = x * y mod l, and returns s.

fn (Scalar) multiply_add #

fn (mut s Scalar) multiply_add(x Scalar, y Scalar, z Scalar) Scalar

multiply_add sets s = x * y + z mod l, and returns s.

fn (Scalar) negate #

fn (mut s Scalar) negate(x Scalar) Scalar

negate sets s = -x mod l, and returns s.

fn (Scalar) non_adjacent_form #

fn (mut s Scalar) non_adjacent_form(w u32) []i8

non_adjacent_form computes a width-w non-adjacent form for this scalar.

w must be between 2 and 8, or non_adjacent_form will panic.

fn (Scalar) set #

fn (mut s Scalar) set(x Scalar) Scalar

set sets s = x, and returns s.

fn (Scalar) set_bytes_with_clamping #

fn (mut s Scalar) set_bytes_with_clamping(x []u8) ?Scalar

set_bytes_with_clamping applies the buffer pruning described in RFC 8032, Section 5.1.5 (also known as clamping) and sets s to the result. The input must be 32 bytes, and it is not modified. If x is not of the right length, set_bytes_with_clamping returns an error, and the receiver is unchanged.

Note that since Scalar values are always reduced modulo the prime order of the curve, the resulting value will not preserve any of the cofactor-clearing properties that clamping is meant to provide. It will however work as expected as long as it is applied to points on the prime order subgroup, like in Ed25519. In fact, it is lost to history why RFC 8032 adopted the irrelevant RFC 7748 clamping, but it is now required for compatibility.

fn (Scalar) set_canonical_bytes #

fn (mut s Scalar) set_canonical_bytes(x []u8) ?Scalar

set_canonical_bytes sets s = x, where x is a 32-byte little-endian encoding of s, and returns s. If x is not a canonical encoding of s, set_canonical_bytes returns an error, and the receiver is unchanged.

fn (Scalar) set_uniform_bytes #

fn (mut s Scalar) set_uniform_bytes(x []u8) ?Scalar

set_uniform_bytes sets s to an uniformly distributed value given 64 uniformly distributed random bytes. If x is not of the right length, set_uniform_bytes returns an error, and the receiver is unchanged.

fn (Scalar) subtract #

fn (mut s Scalar) subtract(x Scalar, y Scalar) Scalar

subtract sets s = x - y mod l, and returns s.

struct Element #

struct Element {
mut:
// An element t represents the integer
//     t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204
//
// Between operations, all limbs are expected to be lower than 2^52.
	l0 u64
	l1 u64
	l2 u64
	l3 u64
	l4 u64
}

Element represents an element of the edwards25519 GF(2^255-19). Note that this is not a cryptographically secure group, and should only be used to interact with edwards25519.Point coordinates.

This type works similarly to math/big.Int, and all arguments and receivers are allowed to alias.

The zero value is a valid zero element.

fn (Element) zero #

fn (mut v Element) zero() Element

zero sets v = 0, and returns v.

fn (Element) one #

fn (mut v Element) one() Element

one sets v = 1, and returns v.

fn (Element) reduce #

fn (mut v Element) reduce() Element

reduce reduces v modulo 2^255 - 19 and returns it.

fn (Element) add #

fn (mut v Element) add(a Element, b Element) Element

add sets v = a + b, and returns v.

fn (Element) subtract #

fn (mut v Element) subtract(a Element, b Element) Element

subtract sets v = a - b, and returns v.

fn (Element) negate #

fn (mut v Element) negate(a Element) Element

negate sets v = -a, and returns v.

fn (Element) invert #

fn (mut v Element) invert(z Element) Element

invert sets v = 1/z mod p, and returns v.

If z == 0, invert returns v = 0.

fn (Element) square #

fn (mut v Element) square(x Element) Element

square sets v = x * x, and returns v.

fn (Element) multiply #

fn (mut v Element) multiply(x Element, y Element) Element

multiply sets v = x * y, and returns v.

fn (Element) pow_22523 #

fn (mut v Element) pow_22523(x Element) Element

pow_22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3.

fn (Element) sqrt_ratio #

fn (mut r Element) sqrt_ratio(u Element, v Element) (Element, int)

sqrt_ratio sets r to the non-negative square root of the ratio of u and v.

If u/v is square, sqrt_ratio returns r and 1. If u/v is not square, sqrt_ratio sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, and returns r and 0.

fn (Element) selected #

fn (mut v Element) selected(a Element, b Element, cond int) Element

selected sets v to a if cond == 1, and to b if cond == 0.

fn (Element) is_negative #

fn (mut v Element) is_negative() int

is_negative returns 1 if v is negative, and 0 otherwise.

fn (Element) absolute #

fn (mut v Element) absolute(u Element) Element

absolute sets v to |u|, and returns v.

fn (Element) set #

fn (mut v Element) set(a Element) Element

set sets v = a, and returns v.

fn (Element) set_bytes #

fn (mut v Element) set_bytes(x []u8) ?Element

set_bytes sets v to x, where x is a 32-byte little-endian encoding. If x is not of the right length, SetUniformBytes returns an error, and the receiver is unchanged.

Consistent with RFC 7748, the most significant bit (the high bit of the last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) are accepted. Note that this is laxer than specified by RFC 8032.

fn (Element) bytes #

fn (mut v Element) bytes() []u8

bytes returns the canonical 32-byte little-endian encoding of v.

fn (Element) equal #

fn (mut v Element) equal(ue Element) int

equal returns 1 if v and u are equal, and 0 otherwise.

fn (Element) swap #

fn (mut v Element) swap(mut u Element, cond int)

swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v.

fn (Element) mult_32 #

fn (mut v Element) mult_32(x Element, y u32) Element

mult_32 sets v = x * y, and returns v.

struct Point #

struct Point {
mut:
// The point is internally represented in extended coordinates (x, y, z, T)
// where x = x/z, y = y/z, and xy = T/z per https://eprint.iacr.org/2008/522.
	x Element
	y Element
	z Element
	t Element
// Make the type not comparable (i.e. used with == or as a map key), as
// equivalent points can be represented by different values.
// _ incomparable
}

Point represents a point on the edwards25519 curve.

This type works similarly to math/big.Int, and all arguments and receivers are allowed to alias.

The zero value is NOT valid, and it may be used only as a receiver.

fn (Point) add #

fn (mut v Point) add(p Point, q Point) Point

add sets v = p + q, and returns v.

fn (Point) bytes #

fn (mut v Point) bytes() []u8

bytes returns the canonical 32-byte encoding of v, according to RFC 8032, Section 5.1.2.

fn (Point) bytes_montgomery #

fn (mut v Point) bytes_montgomery() []u8

bytes_montgomery converts v to a point on the birationally-equivalent Curve25519 Montgomery curve, and returns its canonical 32 bytes encoding according to RFC 7748.

Note that bytes_montgomery only encodes the u-coordinate, so v and -v encode to the same value. If v is the identity point, bytes_montgomery returns 32 zero bytes, analogously to the X25519 function.

fn (Point) equal #

fn (mut v Point) equal(u Point) int

equal returns 1 if v is equivalent to u, and 0 otherwise.

fn (Point) mult_by_cofactor #

fn (mut v Point) mult_by_cofactor(p Point) Point

mult_by_cofactor sets v = 8 * p, and returns v.

fn (Point) multi_scalar_mult #

fn (mut v Point) multi_scalar_mult(scalars []Scalar, points []Point) Point

multi_scalar_mult sets v = sum(scalars[i] * points[i]), and returns v.

Execution time depends only on the lengths of the two slices, which must match.

fn (Point) negate #

fn (mut v Point) negate(p Point) Point

negate sets v = -p, and returns v.

fn (Point) scalar_base_mult #

fn (mut v Point) scalar_base_mult(mut x Scalar) Point

scalar_base_mult sets v = x * B, where B is the canonical generator, and returns v.

The scalar multiplication is done in constant time.

fn (Point) scalar_mult #

fn (mut v Point) scalar_mult(mut x Scalar, q Point) Point

scalar_mult sets v = x * q, and returns v.

The scalar multiplication is done in constant time.

fn (Point) set #

fn (mut v Point) set(u Point) Point

set sets v = u, and returns v.

fn (Point) set_bytes #

fn (mut v Point) set_bytes(x []u8) ?Point

set_bytes sets v = x, where x is a 32-byte encoding of v. If x does not represent a valid point on the curve, set_bytes returns an error and the receiver is unchanged. Otherwise, set_bytes returns v.

Note that set_bytes accepts all non-canonical encodings of valid points.
That is, it follows decoding rules that match most implementations in the ecosystem rather than RFC 8032.

fn (Point) subtract #

fn (mut v Point) subtract(p Point, q Point) Point

subtract sets v = p - q, and returns v.

fn (Point) vartime_double_scalar_base_mult #

fn (mut v Point) vartime_double_scalar_base_mult(xa Scalar, aa Point, xb Scalar) Point

vartime_double_scalar_base_mult sets v = a * A + b * B, where B is the canonical generator, and returns v.

Execution time depends on the inputs.

fn (Point) vartime_multiscalar_mult #

fn (mut v Point) vartime_multiscalar_mult(scalars []Scalar, points []Point) Point

vartime_multiscalar_mult sets v = sum(scalars[i] * points[i]), and returns v.

Execution time depends on the inputs.