Pure Go implementation of the Ristretto prime-order group over Edwards25519
go-ristretto ============
Many cryptographic schemes need a group of prime order. Popular and efficient elliptic curves like (Edwards25519 of ed25519 fame) are rarely of prime order. There is, however, a convenient method to construct a prime order group from such curves, called Ristretto proposed by Mike Hamburg.
This is a pure Go implementation of the group operations on the Ristretto prime-order group built from Edwards25519. Documentation is on godoc.
Example: El'Gamal encryption
// Generate an El'Gamal keypair
var secretKey ristretto.Scalar
var publicKey ristretto.Point
secretKey.Rand() // generate a new secret key publicKey.ScalarMultBase(&secretKey) // compute public key
// El'Gamal encrypt a random curve point p into a ciphertext-pair (c1,c2) var p ristretto.Point var r ristretto.Scalar var c1 ristretto.Point var c2 ristretto.Point p.Rand() r.Rand() c2.ScalarMultBase(&r) c1.PublicScalarMult(&publicKey, &r) c1.Add(&c1, &p)
// Decrypt (c1,c2) back to p var blinding, p2 ristretto.Point blinding.ScalarMult(&c2, &secretKey) p2.Sub(&c1, &blinding)
fmt.Printf("%v", bytes.Equal(p.Bytes(), p2.Bytes())) // Output: // true
Compatibility with ristretto255 RFC draft
An RFC has been proposed to standardise Ristretto over Ed25519. This RFC is compatible with go-ristretto. There is one caveat: one should use Point.DeriveDalek instead of Point.Derive to derive a point from a string.
References
The curve and Ristretto implementation is based on the unpublished PandA library by Chuengsatiansup, Ribarski and Schwabe, see cref/cref.c. The old generic radix 25.5 field operations borrow from Adam Langley's ed25519. The amd64 optimized field arithmetic are from George Tankersley's ed25519 patch, which in turn is based on SUPERCOP's amd64-51-30k by Bernstein, Duif, Lange, Schwabe and Yang. The new generic radix 51 field operations are also based on amd64-51-30k. The variable-time scalar multiplication code is based on that of curve25519-dalek. The Lizard encoding was proposed by Bram Westerbaan. The quick RistrettoElligator inversion for it is joint work with Bram Westerbaan and Mike Hamburg.
other platforms
Changes
1.2.3 (16-03-2023)
- Panic when reading randomness fails.
1.2.2 (29-07-2022)
- Add Point.ConditionalSet() and Scalar.ConditionalSet().
1.2.1 (08-11-2021)
- Add Scalar.SetUint64().
1.2.0 (17-02-2021)
- Add Point.Double(). See issue #21.
- To align more closely with the RFC, Point.SetBytes()
1.1.1 (24-09-2019)
- Only use bits.Add64 from Go 1.13 onwards to make sure we're constant-time
1.1.0 (13-05-2019)
- Add support for the Lizard 16-bytes-to-point-injection.
ristretto.Point.{SetLizard(), Lizard(),LizardInto()}.
- Add
Scalar.DeriveShort()to derive a half-length scalar.
- (internal) Add
ExtendedPoint.RistrettoElligator2Inverse()to compute
CompletedPoint.SetRistrettoElligator2().