forked from Wollac/iota-crypto-demo
/
canonical.go
55 lines (49 loc) · 1.48 KB
/
canonical.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
package vrf
import (
"bytes"
"errors"
"filippo.io/edwards25519"
)
var ErrNonCanonical = errors.New("non canonical point encoding")
var nonCanonicalSignBytes = [...][]byte{
// y = 1, sign-"
{
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
},
// y = p-1, sign-
{
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
},
}
// newPointFromCanonicalBytes creates a new point from the encoding x.
// It compatible with string_to_point from RFC 8032 and returns an error if x is non-canonical.
func newPointFromCanonicalBytes(x []byte) (*edwards25519.Point, error) {
if !isCanonicalY(x) {
return nil, ErrNonCanonical
}
// test for the two cases with a canonically encoded y with a non-canonical sign bit
if bytes.Equal(x, nonCanonicalSignBytes[0]) || bytes.Equal(x, nonCanonicalSignBytes[1]) {
return nil, ErrNonCanonical
}
return new(edwards25519.Point).SetBytes(x)
}
// isCanonicalY checks whether the Y-part of x represents a canonical encoding using the succeed-fast algorithm from
// the "Taming the many EdDSAs" paper.
func isCanonicalY(x []byte) bool {
_ = x[31]
if x[0] < 237 {
return true
}
for i := 1; i <= 30; i++ {
if x[i] != 255 {
return true
}
}
return x[31]|128 != 255
}