forked from gtank/ristretto255
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfe.go
111 lines (97 loc) · 2.55 KB
/
fe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2019 The Go Authors. All rights reserved.
// 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
import (
"math/big"
"github.com/gtank/ristretto255/internal/radix51"
)
// fePow22523 sets out to z^((p-5)/8). (p-5)/8 is 2^252-3.
func fePow22523(out, z *radix51.FieldElement) *radix51.FieldElement {
// Refactored from golang.org/x/crypto/ed25519/internal/edwards25519.
var t0, t1, t2 radix51.FieldElement
t0.Square(z)
for i := 1; i < 1; i++ {
t0.Square(&t0)
}
t1.Square(&t0)
for i := 1; i < 2; i++ {
t1.Square(&t1)
}
t1.Mul(z, &t1)
t0.Mul(&t0, &t1)
t0.Square(&t0)
for i := 1; i < 1; i++ {
t0.Square(&t0)
}
t0.Mul(&t1, &t0)
t1.Square(&t0)
for i := 1; i < 5; i++ {
t1.Square(&t1)
}
t0.Mul(&t1, &t0)
t1.Square(&t0)
for i := 1; i < 10; i++ {
t1.Square(&t1)
}
t1.Mul(&t1, &t0)
t2.Square(&t1)
for i := 1; i < 20; i++ {
t2.Square(&t2)
}
t1.Mul(&t2, &t1)
t1.Square(&t1)
for i := 1; i < 10; i++ {
t1.Square(&t1)
}
t0.Mul(&t1, &t0)
t1.Square(&t0)
for i := 1; i < 50; i++ {
t1.Square(&t1)
}
t1.Mul(&t1, &t0)
t2.Square(&t1)
for i := 1; i < 100; i++ {
t2.Square(&t2)
}
t1.Mul(&t2, &t1)
t1.Square(&t1)
for i := 1; i < 50; i++ {
t1.Square(&t1)
}
t0.Mul(&t1, &t0)
t0.Square(&t0)
for i := 1; i < 2; i++ {
t0.Square(&t0)
}
return out.Mul(&t0, z)
}
// feSqrtRatio sets r to the square root of the ratio of u and v, according to
// Section 3.1.3 of draft-hdevalence-cfrg-ristretto-00.
func feSqrtRatio(r, u, v *radix51.FieldElement) (wasSquare int) {
var a, b radix51.FieldElement
v3 := a.Mul(a.Square(v), v) // v^3 = v^2 * v
v7 := b.Mul(b.Square(v3), v) // v^7 = (v^3)^2 * v
// r = (u * v3) * (u * v7)^((p-5)/8)
uv3 := a.Mul(u, v3) // (u * v3)
uv7 := b.Mul(u, v7) // (u * v7)
r.Mul(uv3, fePow22523(r, uv7))
check := a.Mul(v, a.Square(r)) // check = v * r^2
uNeg := b.Neg(u)
correctSignSqrt := check.Equal(u)
flippedSignSqrt := check.Equal(uNeg)
flippedSignSqrtI := check.Equal(uNeg.Mul(uNeg, sqrtM1))
rPrime := b.Mul(r, sqrtM1) // r_prime = SQRT_M1 * r
// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI)
r.Abs(r) // Choose the nonnegative square root.
return correctSignSqrt | flippedSignSqrt
}
func fieldElementFromDecimal(s string) *radix51.FieldElement {
n, ok := new(big.Int).SetString(s, 10)
if !ok {
panic("ristretto255: not a valid decimal: " + s)
}
return new(radix51.FieldElement).FromBig(n)
}