package nistec
import (
)
const p384ElementLength = 48
type P384Point struct {
x, y, z *fiat.P384Element
}
func () *P384Point {
return &P384Point{
x: new(fiat.P384Element),
y: new(fiat.P384Element).One(),
z: new(fiat.P384Element),
}
}
func ( *P384Point) () *P384Point {
.x.SetBytes([]byte{0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x5, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x2, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0xa, 0xb7})
.y.SetBytes([]byte{0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0xa, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0xe, 0x5f})
.z.One()
return
}
func ( *P384Point) ( *P384Point) *P384Point {
.x.Set(.x)
.y.Set(.y)
.z.Set(.z)
return
}
func ( *P384Point) ( []byte) (*P384Point, error) {
switch {
case len() == 1 && [0] == 0:
return .Set(NewP384Point()), nil
case len() == 1+2*p384ElementLength && [0] == 4:
, := new(fiat.P384Element).SetBytes([1 : 1+p384ElementLength])
if != nil {
return nil,
}
, := new(fiat.P384Element).SetBytes([1+p384ElementLength:])
if != nil {
return nil,
}
if := p384CheckOnCurve(, ); != nil {
return nil,
}
.x.Set()
.y.Set()
.z.One()
return , nil
case len() == 1+p384ElementLength && ([0] == 2 || [0] == 3):
, := new(fiat.P384Element).SetBytes([1:])
if != nil {
return nil,
}
:= p384Polynomial(new(fiat.P384Element), )
if !p384Sqrt(, ) {
return nil, errors.New("invalid P384 compressed point encoding")
}
:= new(fiat.P384Element)
.Sub(, )
:= .Bytes()[p384ElementLength-1]&1 ^ [0]&1
.Select(, , int())
.x.Set()
.y.Set()
.z.One()
return , nil
default:
return nil, errors.New("invalid P384 point encoding")
}
}
var _p384B *fiat.P384Element
var _p384BOnce sync.Once
func () *fiat.P384Element {
_p384BOnce.Do(func() {
_p384B, _ = new(fiat.P384Element).SetBytes([]byte{0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x5, 0x6b, 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, 0x3, 0x14, 0x8, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef})
})
return _p384B
}
func (, *fiat.P384Element) *fiat.P384Element {
.Square()
.Mul(, )
:= new(fiat.P384Element).Add(, )
.Add(, )
.Sub(, )
return .Add(, p384B())
}
func (, *fiat.P384Element) error {
:= p384Polynomial(new(fiat.P384Element), )
:= new(fiat.P384Element).Square()
if .Equal() != 1 {
return errors.New("P384 point not on curve")
}
return nil
}
func ( *P384Point) () []byte {
var [1 + 2*p384ElementLength]byte
return .bytes(&)
}
func ( *P384Point) ( *[1 + 2*p384ElementLength]byte) []byte {
if .z.IsZero() == 1 {
return append([:0], 0)
}
:= new(fiat.P384Element).Invert(.z)
:= new(fiat.P384Element).Mul(.x, )
:= new(fiat.P384Element).Mul(.y, )
:= append([:0], 4)
= append(, .Bytes()...)
= append(, .Bytes()...)
return
}
func ( *P384Point) () ([]byte, error) {
var [p384ElementLength]byte
return .bytesX(&)
}
func ( *P384Point) ( *[p384ElementLength]byte) ([]byte, error) {
if .z.IsZero() == 1 {
return nil, errors.New("P384 point is the point at infinity")
}
:= new(fiat.P384Element).Invert(.z)
:= new(fiat.P384Element).Mul(.x, )
return append([:0], .Bytes()...), nil
}
func ( *P384Point) () []byte {
var [1 + p384ElementLength]byte
return .bytesCompressed(&)
}
func ( *P384Point) ( *[1 + p384ElementLength]byte) []byte {
if .z.IsZero() == 1 {
return append([:0], 0)
}
:= new(fiat.P384Element).Invert(.z)
:= new(fiat.P384Element).Mul(.x, )
:= new(fiat.P384Element).Mul(.y, )
:= append([:0], 2)
[0] |= .Bytes()[p384ElementLength-1] & 1
= append(, .Bytes()...)
return
}
func ( *P384Point) (, *P384Point) *P384Point {
:= new(fiat.P384Element).Mul(.x, .x)
:= new(fiat.P384Element).Mul(.y, .y)
:= new(fiat.P384Element).Mul(.z, .z)
:= new(fiat.P384Element).Add(.x, .y)
:= new(fiat.P384Element).Add(.x, .y)
.Mul(, )
.Add(, )
.Sub(, )
.Add(.y, .z)
:= new(fiat.P384Element).Add(.y, .z)
.Mul(, )
.Add(, )
.Sub(, )
.Add(.x, .z)
:= new(fiat.P384Element).Add(.x, .z)
.Mul(, )
.Add(, )
.Sub(, )
:= new(fiat.P384Element).Mul(p384B(), )
.Sub(, )
.Add(, )
.Add(, )
.Sub(, )
.Add(, )
.Mul(p384B(), )
.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 ( *P384Point) ( *P384Point) *P384Point {
:= new(fiat.P384Element).Square(.x)
:= new(fiat.P384Element).Square(.y)
:= new(fiat.P384Element).Square(.z)
:= new(fiat.P384Element).Mul(.x, .y)
.Add(, )
:= new(fiat.P384Element).Mul(.x, .z)
.Add(, )
:= new(fiat.P384Element).Mul(p384B(), )
.Sub(, )
:= new(fiat.P384Element).Add(, )
.Add(, )
.Sub(, )
.Add(, )
.Mul(, )
.Mul(, )
.Add(, )
.Add(, )
.Mul(p384B(), )
.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 ( *P384Point) (, *P384Point, int) *P384Point {
.x.Select(.x, .x, )
.y.Select(.y, .y, )
.z.Select(.z, .z, )
return
}
type p384Table [15]*P384Point
func ( *p384Table) ( *P384Point, uint8) {
if >= 16 {
panic("nistec: internal error: p384Table called with out-of-bounds value")
}
.Set(NewP384Point())
for := uint8(1); < 16; ++ {
:= subtle.ConstantTimeByteEq(, )
.Select([-1], , )
}
}
func ( *P384Point) ( *P384Point, []byte) (*P384Point, error) {
var = p384Table{NewP384Point(), NewP384Point(), NewP384Point(),
NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point(),
NewP384Point(), NewP384Point(), NewP384Point(), NewP384Point()}
[0].Set()
for := 1; < 15; += 2 {
[].Double([/2])
[+1].Add([], )
}
:= NewP384Point()
.Set(NewP384Point())
for , := range {
if != 0 {
.Double()
.Double()
.Double()
.Double()
}
:= >> 4
.Select(, )
.Add(, )
.Double()
.Double()
.Double()
.Double()
= & 0b1111
.Select(, )
.Add(, )
}
return , nil
}
var p384GeneratorTable *[p384ElementLength * 2]p384Table
var p384GeneratorTableOnce sync.Once
func ( *P384Point) () *[p384ElementLength * 2]p384Table {
p384GeneratorTableOnce.Do(func() {
p384GeneratorTable = new([p384ElementLength * 2]p384Table)
:= NewP384Point().SetGenerator()
for := 0; < p384ElementLength*2; ++ {
p384GeneratorTable[][0] = NewP384Point().Set()
for := 1; < 15; ++ {
p384GeneratorTable[][] = NewP384Point().Add(p384GeneratorTable[][-1], )
}
.Double()
.Double()
.Double()
.Double()
}
})
return p384GeneratorTable
}
func ( *P384Point) ( []byte) (*P384Point, error) {
if len() != p384ElementLength {
return nil, errors.New("invalid scalar length")
}
:= .generatorTable()
:= NewP384Point()
.Set(NewP384Point())
:= len() - 1
for , := range {
:= >> 4
[].Select(, )
.Add(, )
--
= & 0b1111
[].Select(, )
.Add(, )
--
}
return , nil
}
func (, *fiat.P384Element) ( bool) {
:= new(fiat.P384Element)
p384SqrtCandidate(, )
:= new(fiat.P384Element).Square()
if .Equal() != 1 {
return false
}
.Set()
return true
}
func (, *fiat.P384Element) {
var = new(fiat.P384Element)
var = new(fiat.P384Element)
var = new(fiat.P384Element)
.Square()
.Mul(, )
.Square()
.Mul(, )
.Square()
for := 1; < 3; ++ {
.Square()
}
.Mul(, )
.Square()
.Mul(, )
for := 0; < 5; ++ {
.Square()
}
.Mul(, )
.Square()
for := 1; < 12; ++ {
.Square()
}
.Mul(, )
for := 0; < 7; ++ {
.Square()
}
.Mul(, )
.Square()
.Mul(, )
.Square()
for := 1; < 31; ++ {
.Square()
}
.Mul(, )
.Square()
for := 1; < 63; ++ {
.Square()
}
.Mul(, )
.Square()
for := 1; < 126; ++ {
.Square()
}
.Mul(, )
for := 0; < 3; ++ {
.Square()
}
.Mul(, )
for := 0; < 33; ++ {
.Square()
}
.Mul(, )
for := 0; < 64; ++ {
.Square()
}
.Mul(, )
for := 0; < 30; ++ {
.Square()
}
}