-
Notifications
You must be signed in to change notification settings - Fork 1
/
curve.go
97 lines (80 loc) · 2.25 KB
/
curve.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
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
// https://spdx.org/licenses/MIT.html
package nist
import (
"crypto"
"math/big"
"github.com/bytemare/hash2curve"
"github.com/bytemare/crypto/internal/field"
"github.com/bytemare/crypto/internal/h2c"
)
type mapping struct {
z big.Int
hash crypto.Hash
secLength int
}
type curve[point nistECPoint[point]] struct {
field field.Field
b big.Int
NewPoint func() point
mapping
}
func (c *curve[point]) setMapping(hash crypto.Hash, z string, secLength int) {
c.mapping.hash = hash
c.mapping.secLength = secLength
c.mapping.z = field.String2Int(z)
}
func (c *curve[point]) setCurveParams(prime *big.Int, b string, newPoint func() point) {
c.field = field.NewField(prime)
c.b = field.String2Int(b)
c.NewPoint = newPoint
}
func (c *curve[point]) encodeXMD(input, dst []byte) point {
u := hash2curve.HashToFieldXMD(c.hash, input, dst, 1, 1, c.secLength, c.field.Order())
q := c.map2curve(u[0])
// We can save cofactor clearing because it is 1.
return q
}
func (c *curve[point]) hashXMD(input, dst []byte) point {
u := hash2curve.HashToFieldXMD(c.hash, input, dst, 2, 1, c.secLength, c.field.Order())
q0 := c.map2curve(u[0])
q1 := c.map2curve(u[1])
// We can save cofactor clearing because it is 1.
return q0.Add(q0, q1)
}
func (c *curve[point]) map2curve(fe *big.Int) point {
x, y := h2c.MapToCurveSSWU(&c.field, &nistWa, &c.b, &c.z, fe)
return c.affineToPoint(x, y)
}
var (
decompressed256 = [65]byte{0x04}
decompressed384 = [97]byte{0x04}
decompressed521 = [133]byte{0x04}
)
func (c *curve[point]) affineToPoint(pxc, pyc *big.Int) point {
var decompressed []byte
byteLen := (c.field.BitLen() + 7) / 8
switch byteLen {
case 32:
decompressed = decompressed256[:]
case 48:
decompressed = decompressed384[:]
case 66:
decompressed = decompressed521[:]
default:
panic("invalid byte length")
}
decompressed[0] = 0x04
pxc.FillBytes(decompressed[1 : 1+byteLen])
pyc.FillBytes(decompressed[1+byteLen:])
p, err := c.NewPoint().SetBytes(decompressed)
if err != nil {
panic(err)
}
return p
}