1
2
3
4
5
6
7 package fiat
8
9 import (
10 "crypto/subtle"
11 "errors"
12 )
13
14
15
16
17 type P521Element struct {
18
19
20 x p521MontgomeryDomainFieldElement
21 }
22
23 const p521ElementLen = 66
24
25 type p521UntypedFieldElement = [9]uint64
26
27
28 func (e *P521Element) One() *P521Element {
29 p521SetOne(&e.x)
30 return e
31 }
32
33
34 func (e *P521Element) Equal(t *P521Element) int {
35 eBytes := e.Bytes()
36 tBytes := t.Bytes()
37 return subtle.ConstantTimeCompare(eBytes, tBytes)
38 }
39
40 var p521ZeroEncoding = new(P521Element).Bytes()
41
42
43 func (e *P521Element) IsZero() int {
44 eBytes := e.Bytes()
45 return subtle.ConstantTimeCompare(eBytes, p521ZeroEncoding)
46 }
47
48
49 func (e *P521Element) Set(t *P521Element) *P521Element {
50 e.x = t.x
51 return e
52 }
53
54
55 func (e *P521Element) Bytes() []byte {
56
57
58 var out [p521ElementLen]byte
59 return e.bytes(&out)
60 }
61
62 func (e *P521Element) bytes(out *[p521ElementLen]byte) []byte {
63 var tmp p521NonMontgomeryDomainFieldElement
64 p521FromMontgomery(&tmp, &e.x)
65 p521ToBytes(out, (*p521UntypedFieldElement)(&tmp))
66 p521InvertEndianness(out[:])
67 return out[:]
68 }
69
70
71
72
73 var p521MinusOneEncoding = new(P521Element).Sub(
74 new(P521Element), new(P521Element).One()).Bytes()
75
76
77
78
79 func (e *P521Element) SetBytes(v []byte) (*P521Element, error) {
80 if len(v) != p521ElementLen {
81 return nil, errors.New("invalid P521Element encoding")
82 }
83 for i := range v {
84 if v[i] < p521MinusOneEncoding[i] {
85 break
86 }
87 if v[i] > p521MinusOneEncoding[i] {
88 return nil, errors.New("invalid P521Element encoding")
89 }
90 }
91 var in [p521ElementLen]byte
92 copy(in[:], v)
93 p521InvertEndianness(in[:])
94 var tmp p521NonMontgomeryDomainFieldElement
95 p521FromBytes((*p521UntypedFieldElement)(&tmp), &in)
96 p521ToMontgomery(&e.x, &tmp)
97 return e, nil
98 }
99
100
101 func (e *P521Element) Add(t1, t2 *P521Element) *P521Element {
102 p521Add(&e.x, &t1.x, &t2.x)
103 return e
104 }
105
106
107 func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element {
108 p521Sub(&e.x, &t1.x, &t2.x)
109 return e
110 }
111
112
113 func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element {
114 p521Mul(&e.x, &t1.x, &t2.x)
115 return e
116 }
117
118
119 func (e *P521Element) Square(t *P521Element) *P521Element {
120 p521Square(&e.x, &t.x)
121 return e
122 }
123
124
125 func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element {
126 p521Selectznz((*p521UntypedFieldElement)(&v.x), p521Uint1(cond),
127 (*p521UntypedFieldElement)(&b.x), (*p521UntypedFieldElement)(&a.x))
128 return v
129 }
130
131 func p521InvertEndianness(v []byte) {
132 for i := 0; i < len(v)/2; i++ {
133 v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
134 }
135 }
136
View as plain text