package nistec
import (
)
const p224ElementLength = 28
type P224Point struct {
x, y, z *fiat.P224Element
}
func () *P224Point {
return &P224Point{
x: new(fiat.P224Element),
y: new(fiat.P224Element).One(),
z: new(fiat.P224Element),
}
}
func ( *P224Point) () *P224Point {
.x.SetBytes([]byte{0xb7, 0xe, 0xc, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x3, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, 0x11, 0x5c, 0x1d, 0x21})
.y.SetBytes([]byte{0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x7, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, 0x85, 0x0, 0x7e, 0x34})
.z.One()
return
}
func ( *P224Point) ( *P224Point) *P224Point {
.x.Set(.x)
.y.Set(.y)
.z.Set(.z)
return
}
func ( *P224Point) ( []byte) (*P224Point, error) {
switch {
case len() == 1 && [0] == 0:
return .Set(NewP224Point()), nil
case len() == 1+2*p224ElementLength && [0] == 4:
, := new(fiat.P224Element).SetBytes([1 : 1+p224ElementLength])
if != nil {
return nil,
}
, := new(fiat.P224Element).SetBytes([1+p224ElementLength:])
if != nil {
return nil,
}
if := p224CheckOnCurve(, ); != nil {
return nil,
}
.x.Set()
.y.Set()
.z.One()
return , nil
case len() == 1+p224ElementLength && ([0] == 2 || [0] == 3):
, := new(fiat.P224Element).SetBytes([1:])
if != nil {
return nil,
}
:= p224Polynomial(new(fiat.P224Element), )
if !p224Sqrt(, ) {
return nil, errors.New("invalid P224 compressed point encoding")
}
:= new(fiat.P224Element)
.Sub(, )
:= .Bytes()[p224ElementLength-1]&1 ^ [0]&1
.Select(, , int())
.x.Set()
.y.Set()
.z.One()
return , nil
default:
return nil, errors.New("invalid P224 point encoding")
}
}
var _p224B *fiat.P224Element
var _p224BOnce sync.Once
func () *fiat.P224Element {
_p224BOnce.Do(func() {
_p224B, _ = new(fiat.P224Element).SetBytes([]byte{0xb4, 0x5, 0xa, 0x85, 0xc, 0x4, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0xb, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4})
})
return _p224B
}
func (, *fiat.P224Element) *fiat.P224Element {
.Square()
.Mul(, )
:= new(fiat.P224Element).Add(, )
.Add(, )
.Sub(, )
return .Add(, p224B())
}
func (, *fiat.P224Element) error {
:= p224Polynomial(new(fiat.P224Element), )
:= new(fiat.P224Element).Square()
if .Equal() != 1 {
return errors.New("P224 point not on curve")
}
return nil
}
func ( *P224Point) () []byte {
var [1 + 2*p224ElementLength]byte
return .bytes(&)
}
func ( *P224Point) ( *[1 + 2*p224ElementLength]byte) []byte {
if .z.IsZero() == 1 {
return append([:0], 0)
}
:= new(fiat.P224Element).Invert(.z)
:= new(fiat.P224Element).Mul(.x, )
:= new(fiat.P224Element).Mul(.y, )
:= append([:0], 4)
= append(, .Bytes()...)
= append(, .Bytes()...)
return
}
func ( *P224Point) () ([]byte, error) {
var [p224ElementLength]byte
return .bytesX(&)
}
func ( *P224Point) ( *[p224ElementLength]byte) ([]byte, error) {
if .z.IsZero() == 1 {
return nil, errors.New("P224 point is the point at infinity")
}
:= new(fiat.P224Element).Invert(.z)
:= new(fiat.P224Element).Mul(.x, )
return append([:0], .Bytes()...), nil
}
func ( *P224Point) () []byte {
var [1 + p224ElementLength]byte
return .bytesCompressed(&)
}
func ( *P224Point) ( *[1 + p224ElementLength]byte) []byte {
if .z.IsZero() == 1 {
return append([:0], 0)
}
:= new(fiat.P224Element).Invert(.z)
:= new(fiat.P224Element).Mul(.x, )
:= new(fiat.P224Element).Mul(.y, )
:= append([:0], 2)
[0] |= .Bytes()[p224ElementLength-1] & 1
= append(, .Bytes()...)
return
}
func ( *P224Point) (, *P224Point) *P224Point {
:= new(fiat.P224Element).Mul(.x, .x)
:= new(fiat.P224Element).Mul(.y, .y)
:= new(fiat.P224Element).Mul(.z, .z)
:= new(fiat.P224Element).Add(.x, .y)
:= new(fiat.P224Element).Add(.x, .y)
.Mul(, )
.Add(, )
.Sub(, )
.Add(.y, .z)
:= new(fiat.P224Element).Add(.y, .z)
.Mul(, )
.Add(, )
.Sub(, )
.Add(.x, .z)
:= new(fiat.P224Element).Add(.x, .z)
.Mul(, )
.Add(, )
.Sub(, )
:= new(fiat.P224Element).Mul(p224B(), )
.Sub(, )
.Add(, )
.Add(, )
.Sub(, )
.Add(, )
.Mul(p224B(), )
.Add(, )
.Add(, )
.Sub(, )
.Sub(, )
.Add(, )
.Add(, )
.Add(, )
.Add(, )
.Sub(, )
.Mul(, )
.Mul(, )
.Mul(, )
.Add(, )
.Mul(, )
.Sub(, )
.Mul(, )
.Mul(, )
.Add(, )
.x.Set()
.y.Set()
.z.Set()
return
}
func ( *P224Point) ( *P224Point) *P224Point {
:= new(fiat.P224Element).Square(.x)
:= new(fiat.P224Element).Square(.y)
:= new(fiat.P224Element).Square(.z)
:= new(fiat.P224Element).Mul(.x, .y)
.Add(, )
:= new(fiat.P224Element).Mul(.x, .z)
.Add(, )
:= new(fiat.P224Element).Mul(p224B(), )
.Sub(, )
:= new(fiat.P224Element).Add(, )
.Add(, )
.Sub(, )
.Add(, )
.Mul(, )
.Mul(, )
.Add(, )
.Add(, )
.Mul(p224B(), )
.Sub(, )
.Sub(, )
.Add(, )
.Add(, )
.Add(, )
.Add(, )
.Sub(, )
.Mul(, )
.Add(, )
.Mul(.y, .z)
.Add(, )
.Mul(, )
.Sub(, )
.Mul(, )
.Add(, )
.Add(, )
.x.Set()
.y.Set()
.z.Set()
return
}
func ( *P224Point) (, *P224Point, int) *P224Point {
.x.Select(.x, .x, )
.y.Select(.y, .y, )
.z.Select(.z, .z, )
return
}
type p224Table [15]*P224Point
func ( *p224Table) ( *P224Point, uint8) {
if >= 16 {
panic("nistec: internal error: p224Table called with out-of-bounds value")
}
.Set(NewP224Point())
for := uint8(1); < 16; ++ {
:= subtle.ConstantTimeByteEq(, )
.Select([-1], , )
}
}
func ( *P224Point) ( *P224Point, []byte) (*P224Point, error) {
var = p224Table{NewP224Point(), NewP224Point(), NewP224Point(),
NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point()}
[0].Set()
for := 1; < 15; += 2 {
[].Double([/2])
[+1].Add([], )
}
:= NewP224Point()
.Set(NewP224Point())
for , := range {
if != 0 {
.Double()
.Double()
.Double()
.Double()
}
:= >> 4
.Select(, )
.Add(, )
.Double()
.Double()
.Double()
.Double()
= & 0b1111
.Select(, )
.Add(, )
}
return , nil
}
var p224GeneratorTable *[p224ElementLength * 2]p224Table
var p224GeneratorTableOnce sync.Once
func ( *P224Point) () *[p224ElementLength * 2]p224Table {
p224GeneratorTableOnce.Do(func() {
p224GeneratorTable = new([p224ElementLength * 2]p224Table)
:= NewP224Point().SetGenerator()
for := 0; < p224ElementLength*2; ++ {
p224GeneratorTable[][0] = NewP224Point().Set()
for := 1; < 15; ++ {
p224GeneratorTable[][] = NewP224Point().Add(p224GeneratorTable[][-1], )
}
.Double()
.Double()
.Double()
.Double()
}
})
return p224GeneratorTable
}
func ( *P224Point) ( []byte) (*P224Point, error) {
if len() != p224ElementLength {
return nil, errors.New("invalid scalar length")
}
:= .generatorTable()
:= NewP224Point()
.Set(NewP224Point())
:= len() - 1
for , := range {
:= >> 4
[].Select(, )
.Add(, )
--
= & 0b1111
[].Select(, )
.Add(, )
--
}
return , nil
}
func (, *fiat.P224Element) ( bool) {
:= new(fiat.P224Element)
p224SqrtCandidate(, )
:= new(fiat.P224Element).Square()
if .Equal() != 1 {
return false
}
.Set()
return true
}