1 package group
2
3 import (
4 "crypto"
5 _ "crypto/sha512"
6 "fmt"
7 "io"
8 "math/big"
9
10 r255 "github.com/bwesterb/go-ristretto"
11 "github.com/cloudflare/circl/expander"
12 "github.com/cloudflare/circl/internal/conv"
13 )
14
15
16 var Ristretto255 Group = ristrettoGroup{}
17
18 type ristrettoGroup struct{}
19
20 func (g ristrettoGroup) String() string {
21 return "ristretto255"
22 }
23
24 func (g ristrettoGroup) Params() *Params {
25 return &Params{32, 32, 32}
26 }
27
28 type ristrettoElement struct {
29 p r255.Point
30 }
31
32 type ristrettoScalar struct {
33 s r255.Scalar
34 }
35
36 func (g ristrettoGroup) NewElement() Element {
37 return g.Identity()
38 }
39
40 func (g ristrettoGroup) NewScalar() Scalar {
41 return &ristrettoScalar{
42 s: r255.Scalar{},
43 }
44 }
45
46 func (g ristrettoGroup) Identity() Element {
47 var zero r255.Point
48 zero.SetZero()
49 return &ristrettoElement{
50 p: zero,
51 }
52 }
53
54 func (g ristrettoGroup) Generator() Element {
55 var base r255.Point
56 base.SetBase()
57 return &ristrettoElement{
58 p: base,
59 }
60 }
61
62 func (g ristrettoGroup) Order() Scalar {
63 q := r255.Scalar{
64 0x5cf5d3ed, 0x5812631a, 0xa2f79cd6, 0x14def9de,
65 0x00000000, 0x00000000, 0x00000000, 0x10000000,
66 }
67 return &ristrettoScalar{
68 s: q,
69 }
70 }
71
72 func (g ristrettoGroup) RandomElement(r io.Reader) Element {
73 var x r255.Point
74 x.Rand()
75 return &ristrettoElement{
76 p: x,
77 }
78 }
79
80 func (g ristrettoGroup) RandomScalar(io.Reader) Scalar {
81 var x r255.Scalar
82 x.Rand()
83 return &ristrettoScalar{
84 s: x,
85 }
86 }
87
88 func (g ristrettoGroup) RandomNonZeroScalar(io.Reader) Scalar {
89 var s r255.Scalar
90 for {
91 s.Rand()
92 if s.IsNonZeroI() == 1 {
93 return &ristrettoScalar{s}
94 }
95 }
96 }
97
98 func (g ristrettoGroup) HashToElementNonUniform(b, dst []byte) Element {
99 return g.HashToElement(b, dst)
100 }
101
102 func (g ristrettoGroup) HashToElement(msg, dst []byte) Element {
103
104
105
106
107 var buf [32]byte
108 xmd := expander.NewExpanderMD(crypto.SHA512, dst)
109 uniformBytes := xmd.Expand(msg, 64)
110 copy(buf[:], uniformBytes[:32])
111 p0 := new(r255.Point).SetElligator(&buf)
112 copy(buf[:], uniformBytes[32:])
113 p1 := new(r255.Point).SetElligator(&buf)
114 p0.Add(p0, p1)
115
116 return &ristrettoElement{*p0}
117 }
118
119 func (g ristrettoGroup) HashToScalar(msg, dst []byte) Scalar {
120
121
122
123 var uniformBytes [64]byte
124 xmd := expander.NewExpanderMD(crypto.SHA512, dst)
125 copy(uniformBytes[:], xmd.Expand(msg, 64))
126 s := g.NewScalar()
127 s.(*ristrettoScalar).s.SetReduced(&uniformBytes)
128 return s
129 }
130
131 func (e *ristrettoElement) Group() Group { return Ristretto255 }
132
133 func (e *ristrettoElement) String() string { return fmt.Sprintf("%x", e.p.Bytes()) }
134
135 func (e *ristrettoElement) IsIdentity() bool {
136 var zero r255.Point
137 zero.SetZero()
138 return e.p.Equals(&zero)
139 }
140
141 func (e *ristrettoElement) IsEqual(x Element) bool {
142 return e.p.Equals(&x.(*ristrettoElement).p)
143 }
144
145 func (e *ristrettoElement) Set(x Element) Element {
146 e.p.Set(&x.(*ristrettoElement).p)
147 return e
148 }
149
150 func (e *ristrettoElement) Copy() Element {
151 return &ristrettoElement{*new(r255.Point).Set(&e.p)}
152 }
153
154 func (e *ristrettoElement) CMov(v int, x Element) Element {
155 if !(v == 0 || v == 1) {
156 panic(ErrSelector)
157 }
158 e.p.ConditionalSet(&x.(*ristrettoElement).p, int32(v))
159 return e
160 }
161
162 func (e *ristrettoElement) CSelect(v int, x Element, y Element) Element {
163 if !(v == 0 || v == 1) {
164 panic(ErrSelector)
165 }
166 e.p.ConditionalSet(&x.(*ristrettoElement).p, int32(v))
167 e.p.ConditionalSet(&y.(*ristrettoElement).p, int32(1-v))
168 return e
169 }
170
171 func (e *ristrettoElement) Add(x Element, y Element) Element {
172 e.p.Add(&x.(*ristrettoElement).p, &y.(*ristrettoElement).p)
173 return e
174 }
175
176 func (e *ristrettoElement) Dbl(x Element) Element {
177 return e.Add(x, x)
178 }
179
180 func (e *ristrettoElement) Neg(x Element) Element {
181 e.p.Neg(&x.(*ristrettoElement).p)
182 return e
183 }
184
185 func (e *ristrettoElement) Mul(x Element, y Scalar) Element {
186 e.p.ScalarMult(&x.(*ristrettoElement).p, &y.(*ristrettoScalar).s)
187 return e
188 }
189
190 func (e *ristrettoElement) MulGen(x Scalar) Element {
191 e.p.ScalarMultBase(&x.(*ristrettoScalar).s)
192 return e
193 }
194
195 func (e *ristrettoElement) MarshalBinaryCompress() ([]byte, error) {
196 return e.p.MarshalBinary()
197 }
198
199 func (e *ristrettoElement) MarshalBinary() ([]byte, error) {
200 return e.p.MarshalBinary()
201 }
202
203 func (e *ristrettoElement) UnmarshalBinary(data []byte) error {
204 return e.p.UnmarshalBinary(data)
205 }
206
207 func (s *ristrettoScalar) Group() Group { return Ristretto255 }
208 func (s *ristrettoScalar) String() string { return conv.BytesLe2Hex(s.s.Bytes()) }
209 func (s *ristrettoScalar) SetUint64(n uint64) Scalar { s.s.SetUint64(n); return s }
210 func (s *ristrettoScalar) SetBigInt(x *big.Int) Scalar { s.s.SetBigInt(x); return s }
211 func (s *ristrettoScalar) IsZero() bool { return s.s.IsNonZeroI() == 0 }
212 func (s *ristrettoScalar) IsEqual(x Scalar) bool {
213 return s.s.Equals(&x.(*ristrettoScalar).s)
214 }
215
216 func (s *ristrettoScalar) Set(x Scalar) Scalar {
217 s.s.Set(&x.(*ristrettoScalar).s)
218 return s
219 }
220
221 func (s *ristrettoScalar) Copy() Scalar {
222 return &ristrettoScalar{*new(r255.Scalar).Set(&s.s)}
223 }
224
225 func (s *ristrettoScalar) CMov(v int, x Scalar) Scalar {
226 if !(v == 0 || v == 1) {
227 panic(ErrSelector)
228 }
229 s.s.ConditionalSet(&x.(*ristrettoScalar).s, int32(v))
230 return s
231 }
232
233 func (s *ristrettoScalar) CSelect(v int, x Scalar, y Scalar) Scalar {
234 if !(v == 0 || v == 1) {
235 panic(ErrSelector)
236 }
237 s.s.ConditionalSet(&x.(*ristrettoScalar).s, int32(v))
238 s.s.ConditionalSet(&y.(*ristrettoScalar).s, int32(1-v))
239 return s
240 }
241
242 func (s *ristrettoScalar) Add(x Scalar, y Scalar) Scalar {
243 s.s.Add(&x.(*ristrettoScalar).s, &y.(*ristrettoScalar).s)
244 return s
245 }
246
247 func (s *ristrettoScalar) Sub(x Scalar, y Scalar) Scalar {
248 s.s.Sub(&x.(*ristrettoScalar).s, &y.(*ristrettoScalar).s)
249 return s
250 }
251
252 func (s *ristrettoScalar) Mul(x Scalar, y Scalar) Scalar {
253 s.s.Mul(&x.(*ristrettoScalar).s, &y.(*ristrettoScalar).s)
254 return s
255 }
256
257 func (s *ristrettoScalar) Neg(x Scalar) Scalar {
258 s.s.Neg(&x.(*ristrettoScalar).s)
259 return s
260 }
261
262 func (s *ristrettoScalar) Inv(x Scalar) Scalar {
263 s.s.Inverse(&x.(*ristrettoScalar).s)
264 return s
265 }
266
267 func (s *ristrettoScalar) MarshalBinary() ([]byte, error) {
268 return s.s.MarshalBinary()
269 }
270
271 func (s *ristrettoScalar) UnmarshalBinary(data []byte) error {
272 return s.s.UnmarshalBinary(data)
273 }
274
View as plain text