edwards25519

repository·main·Indexed 41 days ago

https://github.com/filosottile/edwards25519

A high-performance Go implementation of the edwards25519 elliptic curve. It provides low-level APIs for building higher-level cryptographic primitives, including point arithmetic, scalar multiplication, and multi-scalar multiplication (MSM). The library supports constant-time operations for security-sensitive contexts and provides types for Points and Scalars, tracking the Go standard library's internal fips140 implementation.

Tokens
3.2K
Snippets
22
Records
24
Agent score
50%

What's inside edwards25519

  1. Overview of filippo.io/edwards25519

    main

    The filippo.io/edwards25519 library provides an implementation of the edwards25519 elliptic curve. It is designed to expose the low-level APIs necessary for building higher-level cryptographic primitives. It tracks the Go standard library's crypto/internal/fips140/edwards25519 and extends it with additional functionality.

    Note for most users: If you only need standard cryptographic operations, you should likely use other packages instead of this one:

    • For signatures: use crypto/ed25519.
    • For Diffie-Hellman: use crypto/ecdh.
    • For prime order group logic: use github.com/gtank/ristretto255.

    This package is intended as a replacement for those using forks of the internal Go edwards25519 package or github.com/agl/edwards25519.

  2. The Scalar type and its properties

    main

    A Scalar is an integer modulo the prime order of the edwards25519 group:

    l = 2^252 + 27742317777372353535851937790883648493

    Key characteristics:

    • It behaves similarly to math/big.Int.
    • All arguments and receivers are allowed to alias (the same Scalar can be used as both input and output).
    • The zero value is a valid zero element.
    • Internal representation uses the Montgomery domain (via fiat-crypto).
    type Scalar struct {}
  3. Perform scalar multiplication with ScalarBaseMult

    main

    Use ScalarBaseMult to compute $v = x \cdot B$, where $B$ is the canonical generator (basepoint) of the Edwards25519 curve. This operation is performed in constant time, making it suitable for cryptographic operations where side-channel resistance is required.

    Note that the method is called on a *Point receiver v, which is updated to the result, and it also returns the updated point for chaining.

    // Assuming v is a *Point and x is a *Scalar
    v.ScalarBaseMult(x)
    // v now holds the result of x * B
  4. Encode and decode points using bytes

    main

    Use Bytes() to get the canonical 32-byte encoding of a point according to RFC 8032, Section 5.1.2.

    Use SetBytes(x []byte) to set the point to the value represented by the 32-byte slice x.

    Note on SetBytes:

    • It returns an error if the encoding length is invalid or if the bytes do not represent a valid point on the curve.
    • It accepts non-canonical encodings of valid points (e.g., unreduced field elements or specific sign bit configurations) to maintain compatibility with other implementations in the ecosystem.
    // Encoding a point
    encoded := p.Bytes()
    
    // Decoding a point
    newP := new(edwards25519.Point)
    _, err := newP.SetBytes(encoded)
    if err != nil {
        // handle error
    }
  5. Import Scalars from bytes

    main

    Use these methods to initialize a Scalar from byte slices:

    • SetUniformBytes(x []byte) (*Scalar, error): Sets s = x mod l, where x is a 64-byte little-endian integer. This is useful for setting a scalar to a uniformly distributed value from 64 random bytes.
    • SetCanonicalBytes(x []byte) (*Scalar, error): Sets s = x, where x is a 32-byte little-endian encoding. Returns an error if x is not a canonical encoding (i.e., if it is not reduced modulo l).
    • SetBytesWithClamping(x []byte) (*Scalar, error): Applies RFC 8032 Section 5.1.5 clamping (bit pruning) to a 32-byte input and sets s to the result. This is required for compatibility with Ed25519.
    // Example: Set from canonical bytes
    bytes := make([]byte, 32)
    // ... fill bytes ...
    s, err := s.SetCanonicalBytes(bytes)
    if err != nil {
        // handle error
    }
  6. Perform constant-time selection and conditional negation

    main

    For cryptographic operations requiring constant-time execution, use the Select and CondNeg methods. Note that these methods are implemented on internal cached types (projCached and affineCached), which are typically used during high-performance arithmetic pipelines.

    • Select(a, b, cond): Sets the receiver to a if cond == 1, or b if cond == 0.
    • CondNeg(cond): Negates the point if cond == 1, otherwise leaves it unchanged.
  7. Perform variable-time double scalar multiplication with VarTimeDoubleScalarBaseMult

    main

    Use VarTimeDoubleScalarBaseMult to compute $v = a \cdot A + b \cdot B$, where $B$ is the canonical generator, $A$ is an arbitrary point, and $a, b$ are scalars.

    Warning: This operation is variable-time; its execution time depends on the input values. It should not be used in contexts where side-channel resistance is required. It is optimized for speed using a Non-Adjacent Form (NAF) representation to minimize the number of additions.

    // Assuming v is a *Point, a and b are *Scalar, and A is a *Point
    v.VarTimeDoubleScalarBaseMult(a, A, b)
    // v now holds the result of (a * A) + (b * B)
  8. Perform Multi-Scalar Multiplication (MSM)

    main

    The library provides two methods for computing a sum of multiple scalar-point products: $v = \sum (scalars[i] \cdot points[i])$.

    1. MultiScalarMult(scalars []*Scalar, points []*Point) *Point: A constant-time implementation. The execution time depends only on the lengths of the input slices, which must be equal. Use this for security-sensitive operations.
    2. VarTimeMultiScalarMult(scalars []*Scalar, points []*Point) *Point: A variable-time implementation. The execution time depends on the input values. This may be faster in non-sensitive contexts but is not constant-time.
    // Constant-time MSM
    v.MultiScalarMult(scalars, points)
    
    // Variable-time MSM
    v.VarTimeMultiScalarMult(scalars, points)
  9. Create identity and generator points

    main

    You can initialize points to specific standard values using the following constructors:

    • NewIdentityPoint(): Returns a new Point set to the identity (the point at infinity).
    • NewGeneratorPoint(): Returns a new Point set to the canonical curve basepoint (generator).
    // Returns the identity point
    p := edwards25519.NewIdentityPoint()
    
    // Returns the canonical generator point
    g := edwards25519.NewGeneratorPoint()