2019-01-20 22:36:31 +00:00
|
|
|
// Copyright 2019 The Go Authors. All rights reserved.
|
2019-01-20 22:30:31 +00:00
|
|
|
// Copyright 2019 George Tankersley. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// Package ristretto255 implements the ristretto255 prime-order group as
|
|
|
|
// specified in draft-hdevalence-cfrg-ristretto-00.
|
|
|
|
package ristretto255
|
|
|
|
|
|
|
|
import (
|
2019-04-19 16:22:32 +00:00
|
|
|
"github.com/gtank/ristretto255/internal/edwards25519"
|
2019-01-21 23:13:23 +00:00
|
|
|
"github.com/gtank/ristretto255/internal/radix51"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
sqrtM1 = fieldElementFromDecimal(
|
|
|
|
"19681161376707505956807079304988542015446066515923890162744021073123829784752")
|
|
|
|
sqrtADMinusOne = fieldElementFromDecimal(
|
|
|
|
"25063068953384623474111414158702152701244531502492656460079210482610430750235")
|
|
|
|
invSqrtAMinusD = fieldElementFromDecimal(
|
|
|
|
"54469307008909316920995813868745141605393597292927456921205312896311721017578")
|
|
|
|
oneMinusDSQ = fieldElementFromDecimal(
|
|
|
|
"1159843021668779879193775521855586647937357759715417654439879720876111806838")
|
|
|
|
dMinusOneSQ = fieldElementFromDecimal(
|
|
|
|
"40440834346308536858101042469323190826248399146238708352240133220865137265952")
|
2019-01-20 22:30:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Element is an element of the ristretto255 prime-order group.
|
|
|
|
type Element struct {
|
2019-04-19 16:22:32 +00:00
|
|
|
r edwards25519.ExtendedGroupElement
|
2019-01-20 22:30:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Equal returns 1 if e is equivalent to ee, and 0 otherwise.
|
|
|
|
// Note that Elements must not be compared in any other way.
|
|
|
|
func (e *Element) Equal(ee *Element) int {
|
2019-01-21 23:13:23 +00:00
|
|
|
var f0, f1 radix51.FieldElement
|
2019-01-20 22:30:31 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
f0.Mul(&e.r.X, &ee.r.Y) // x1 * y2
|
|
|
|
f1.Mul(&e.r.Y, &ee.r.X) // y1 * x2
|
|
|
|
out := f0.Equal(&f1)
|
2019-01-20 22:30:31 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
f0.Mul(&e.r.Y, &ee.r.Y) // y1 * y2
|
|
|
|
f1.Mul(&e.r.X, &ee.r.X) // x1 * x2
|
|
|
|
out = out | f0.Equal(&f1)
|
2019-01-20 22:30:31 +00:00
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
2019-01-21 22:43:47 +00:00
|
|
|
|
|
|
|
// FromUniformBytes maps the 64-byte slice b to an Element e uniformly and
|
|
|
|
// deterministically. This can be used for hash-to-group operations or to obtain
|
|
|
|
// a random element.
|
|
|
|
func (e *Element) FromUniformBytes(b []byte) {
|
|
|
|
if len(b) != 64 {
|
2019-01-21 23:13:23 +00:00
|
|
|
panic("ristretto255: FromUniformBytes: input is not 64 bytes long")
|
2019-01-21 22:43:47 +00:00
|
|
|
}
|
|
|
|
|
2019-01-22 04:39:45 +00:00
|
|
|
f := &radix51.FieldElement{}
|
|
|
|
|
2019-03-31 02:22:42 +00:00
|
|
|
f.FromBytes(b[:32])
|
2019-04-19 16:22:32 +00:00
|
|
|
p1 := &edwards25519.ExtendedGroupElement{}
|
2019-01-22 04:39:45 +00:00
|
|
|
mapToPoint(p1, f)
|
|
|
|
|
2019-03-31 02:22:42 +00:00
|
|
|
f.FromBytes(b[32:])
|
2019-04-19 16:22:32 +00:00
|
|
|
p2 := &edwards25519.ExtendedGroupElement{}
|
2019-01-22 04:39:45 +00:00
|
|
|
mapToPoint(p2, f)
|
|
|
|
|
|
|
|
e.r.Add(p1, p2)
|
|
|
|
}
|
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// mapToPoint implements MAP from Section 3.2.4 of draft-hdevalence-cfrg-ristretto-00.
|
2019-04-19 16:22:32 +00:00
|
|
|
func mapToPoint(out *edwards25519.ExtendedGroupElement, t *radix51.FieldElement) {
|
2019-01-27 03:20:45 +00:00
|
|
|
// r = SQRT_M1 * t^2
|
2019-01-22 04:39:45 +00:00
|
|
|
r := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
r.Mul(sqrtM1, r.Square(t))
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// u = (r + 1) * ONE_MINUS_D_SQ
|
2019-01-22 04:39:45 +00:00
|
|
|
u := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
u.Mul(u.Add(r, radix51.One), oneMinusDSQ)
|
|
|
|
|
|
|
|
// c = -1
|
|
|
|
c := &radix51.FieldElement{}
|
|
|
|
c.Set(radix51.MinusOne)
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// v = (c - r*D) * (r + D)
|
2019-01-22 04:39:45 +00:00
|
|
|
rPlusD := &radix51.FieldElement{}
|
2019-04-19 16:22:32 +00:00
|
|
|
rPlusD.Add(r, edwards25519.D)
|
2019-01-22 04:39:45 +00:00
|
|
|
v := &radix51.FieldElement{}
|
2019-04-19 16:22:32 +00:00
|
|
|
v.Mul(v.Sub(c, v.Mul(r, edwards25519.D)), rPlusD)
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// (was_square, s) = SQRT_RATIO_M1(u, v)
|
2019-01-22 04:39:45 +00:00
|
|
|
s := &radix51.FieldElement{}
|
|
|
|
wasSquare := feSqrtRatio(s, u, v)
|
2019-01-27 03:20:45 +00:00
|
|
|
|
|
|
|
// s_prime = -CT_ABS(s*t)
|
2019-01-22 04:39:45 +00:00
|
|
|
sPrime := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
sPrime.Neg(sPrime.Abs(sPrime.Mul(s, t)))
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// s = CT_SELECT(s IF was_square ELSE s_prime)
|
|
|
|
s.Select(s, sPrime, wasSquare)
|
|
|
|
// c = CT_SELECT(c IF was_square ELSE r)
|
|
|
|
c.Select(c, r, wasSquare)
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// N = c * (r - 1) * D_MINUS_ONE_SQ - v
|
2019-01-22 04:39:45 +00:00
|
|
|
N := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
N.Mul(c, N.Sub(r, radix51.One))
|
|
|
|
N.Sub(N.Mul(N, dMinusOneSQ), v)
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
s2 := &radix51.FieldElement{}
|
|
|
|
s2.Square(s)
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// w0 = 2 * s * v
|
2019-01-22 04:39:45 +00:00
|
|
|
w0 := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
w0.Add(w0, w0.Mul(s, v))
|
|
|
|
// w1 = N * SQRT_AD_MINUS_ONE
|
2019-01-22 04:39:45 +00:00
|
|
|
w1 := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
w1.Mul(N, sqrtADMinusOne)
|
|
|
|
// w2 = 1 - s^2
|
2019-01-22 04:39:45 +00:00
|
|
|
w2 := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
w2.Sub(radix51.One, s2)
|
|
|
|
// w3 = 1 + s^2
|
2019-01-22 04:39:45 +00:00
|
|
|
w3 := &radix51.FieldElement{}
|
2019-01-27 03:20:45 +00:00
|
|
|
w3.Add(radix51.One, s2)
|
2019-01-22 04:39:45 +00:00
|
|
|
|
2019-01-27 03:20:45 +00:00
|
|
|
// return (w0*w3, w2*w1, w1*w3, w0*w2)
|
|
|
|
out.X.Mul(w0, w3)
|
|
|
|
out.Y.Mul(w2, w1)
|
|
|
|
out.Z.Mul(w1, w3)
|
|
|
|
out.T.Mul(w0, w2)
|
2019-01-21 22:43:47 +00:00
|
|
|
}
|