package edwards25519
import (
"crypto/internal/edwards25519/field"
"errors"
)
type projP1xP1 struct {
X , Y , Z , T field .Element
}
type projP2 struct {
X , Y , Z field .Element
}
type Point struct {
_ incomparable
x , y , z , t field .Element
}
type incomparable [0 ]func ()
func checkInitialized (points ...*Point ) {
for _ , p := range points {
if p .x == (field .Element {}) && p .y == (field .Element {}) {
panic ("edwards25519: use of uninitialized Point" )
}
}
}
type projCached struct {
YplusX , YminusX , Z , T2d field .Element
}
type affineCached struct {
YplusX , YminusX , T2d field .Element
}
func (v *projP2 ) Zero () *projP2 {
v .X .Zero ()
v .Y .One ()
v .Z .One ()
return v
}
var identity , _ = new (Point ).SetBytes ([]byte {
1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 })
func NewIdentityPoint () *Point {
return new (Point ).Set (identity )
}
var generator , _ = new (Point ).SetBytes ([]byte {
0x58 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 ,
0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 ,
0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 ,
0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 , 0x66 })
func NewGeneratorPoint () *Point {
return new (Point ).Set (generator )
}
func (v *projCached ) Zero () *projCached {
v .YplusX .One ()
v .YminusX .One ()
v .Z .One ()
v .T2d .Zero ()
return v
}
func (v *affineCached ) Zero () *affineCached {
v .YplusX .One ()
v .YminusX .One ()
v .T2d .Zero ()
return v
}
func (v *Point ) Set (u *Point ) *Point {
*v = *u
return v
}
func (v *Point ) Bytes () []byte {
var buf [32 ]byte
return v .bytes (&buf )
}
func (v *Point ) bytes (buf *[32 ]byte ) []byte {
checkInitialized (v )
var zInv , x , y field .Element
zInv .Invert (&v .z )
x .Multiply (&v .x , &zInv )
y .Multiply (&v .y , &zInv )
out := copyFieldElement (buf , &y )
out [31 ] |= byte (x .IsNegative () << 7 )
return out
}
var feOne = new (field .Element ).One ()
func (v *Point ) SetBytes (x []byte ) (*Point , error ) {
y , err := new (field .Element ).SetBytes (x )
if err != nil {
return nil , errors .New ("edwards25519: invalid point encoding length" )
}
y2 := new (field .Element ).Square (y )
u := new (field .Element ).Subtract (y2 , feOne )
vv := new (field .Element ).Multiply (y2 , d )
vv = vv .Add (vv , feOne )
xx , wasSquare := new (field .Element ).SqrtRatio (u , vv )
if wasSquare == 0 {
return nil , errors .New ("edwards25519: invalid point encoding" )
}
xxNeg := new (field .Element ).Negate (xx )
xx = xx .Select (xxNeg , xx , int (x [31 ]>>7 ))
v .x .Set (xx )
v .y .Set (y )
v .z .One ()
v .t .Multiply (xx , y )
return v , nil
}
func copyFieldElement (buf *[32 ]byte , v *field .Element ) []byte {
copy (buf [:], v .Bytes ())
return buf [:]
}
func (v *projP2 ) FromP1xP1 (p *projP1xP1 ) *projP2 {
v .X .Multiply (&p .X , &p .T )
v .Y .Multiply (&p .Y , &p .Z )
v .Z .Multiply (&p .Z , &p .T )
return v
}
func (v *projP2 ) FromP3 (p *Point ) *projP2 {
v .X .Set (&p .x )
v .Y .Set (&p .y )
v .Z .Set (&p .z )
return v
}
func (v *Point ) fromP1xP1 (p *projP1xP1 ) *Point {
v .x .Multiply (&p .X , &p .T )
v .y .Multiply (&p .Y , &p .Z )
v .z .Multiply (&p .Z , &p .T )
v .t .Multiply (&p .X , &p .Y )
return v
}
func (v *Point ) fromP2 (p *projP2 ) *Point {
v .x .Multiply (&p .X , &p .Z )
v .y .Multiply (&p .Y , &p .Z )
v .z .Square (&p .Z )
v .t .Multiply (&p .X , &p .Y )
return v
}
var d , _ = new (field .Element ).SetBytes ([]byte {
0xa3 , 0x78 , 0x59 , 0x13 , 0xca , 0x4d , 0xeb , 0x75 ,
0xab , 0xd8 , 0x41 , 0x41 , 0x4d , 0x0a , 0x70 , 0x00 ,
0x98 , 0xe8 , 0x79 , 0x77 , 0x79 , 0x40 , 0xc7 , 0x8c ,
0x73 , 0xfe , 0x6f , 0x2b , 0xee , 0x6c , 0x03 , 0x52 })
var d2 = new (field .Element ).Add (d , d )
func (v *projCached ) FromP3 (p *Point ) *projCached {
v .YplusX .Add (&p .y , &p .x )
v .YminusX .Subtract (&p .y , &p .x )
v .Z .Set (&p .z )
v .T2d .Multiply (&p .t , d2 )
return v
}
func (v *affineCached ) FromP3 (p *Point ) *affineCached {
v .YplusX .Add (&p .y , &p .x )
v .YminusX .Subtract (&p .y , &p .x )
v .T2d .Multiply (&p .t , d2 )
var invZ field .Element
invZ .Invert (&p .z )
v .YplusX .Multiply (&v .YplusX , &invZ )
v .YminusX .Multiply (&v .YminusX , &invZ )
v .T2d .Multiply (&v .T2d , &invZ )
return v
}
func (v *Point ) Add (p , q *Point ) *Point {
checkInitialized (p , q )
qCached := new (projCached ).FromP3 (q )
result := new (projP1xP1 ).Add (p , qCached )
return v .fromP1xP1 (result )
}
func (v *Point ) Subtract (p , q *Point ) *Point {
checkInitialized (p , q )
qCached := new (projCached ).FromP3 (q )
result := new (projP1xP1 ).Sub (p , qCached )
return v .fromP1xP1 (result )
}
func (v *projP1xP1 ) Add (p *Point , q *projCached ) *projP1xP1 {
var YplusX , YminusX , PP , MM , TT2d , ZZ2 field .Element
YplusX .Add (&p .y , &p .x )
YminusX .Subtract (&p .y , &p .x )
PP .Multiply (&YplusX , &q .YplusX )
MM .Multiply (&YminusX , &q .YminusX )
TT2d .Multiply (&p .t , &q .T2d )
ZZ2 .Multiply (&p .z , &q .Z )
ZZ2 .Add (&ZZ2 , &ZZ2 )
v .X .Subtract (&PP , &MM )
v .Y .Add (&PP , &MM )
v .Z .Add (&ZZ2 , &TT2d )
v .T .Subtract (&ZZ2 , &TT2d )
return v
}
func (v *projP1xP1 ) Sub (p *Point , q *projCached ) *projP1xP1 {
var YplusX , YminusX , PP , MM , TT2d , ZZ2 field .Element
YplusX .Add (&p .y , &p .x )
YminusX .Subtract (&p .y , &p .x )
PP .Multiply (&YplusX , &q .YminusX )
MM .Multiply (&YminusX , &q .YplusX )
TT2d .Multiply (&p .t , &q .T2d )
ZZ2 .Multiply (&p .z , &q .Z )
ZZ2 .Add (&ZZ2 , &ZZ2 )
v .X .Subtract (&PP , &MM )
v .Y .Add (&PP , &MM )
v .Z .Subtract (&ZZ2 , &TT2d )
v .T .Add (&ZZ2 , &TT2d )
return v
}
func (v *projP1xP1 ) AddAffine (p *Point , q *affineCached ) *projP1xP1 {
var YplusX , YminusX , PP , MM , TT2d , Z2 field .Element
YplusX .Add (&p .y , &p .x )
YminusX .Subtract (&p .y , &p .x )
PP .Multiply (&YplusX , &q .YplusX )
MM .Multiply (&YminusX , &q .YminusX )
TT2d .Multiply (&p .t , &q .T2d )
Z2 .Add (&p .z , &p .z )
v .X .Subtract (&PP , &MM )
v .Y .Add (&PP , &MM )
v .Z .Add (&Z2 , &TT2d )
v .T .Subtract (&Z2 , &TT2d )
return v
}
func (v *projP1xP1 ) SubAffine (p *Point , q *affineCached ) *projP1xP1 {
var YplusX , YminusX , PP , MM , TT2d , Z2 field .Element
YplusX .Add (&p .y , &p .x )
YminusX .Subtract (&p .y , &p .x )
PP .Multiply (&YplusX , &q .YminusX )
MM .Multiply (&YminusX , &q .YplusX )
TT2d .Multiply (&p .t , &q .T2d )
Z2 .Add (&p .z , &p .z )
v .X .Subtract (&PP , &MM )
v .Y .Add (&PP , &MM )
v .Z .Subtract (&Z2 , &TT2d )
v .T .Add (&Z2 , &TT2d )
return v
}
func (v *projP1xP1 ) Double (p *projP2 ) *projP1xP1 {
var XX , YY , ZZ2 , XplusYsq field .Element
XX .Square (&p .X )
YY .Square (&p .Y )
ZZ2 .Square (&p .Z )
ZZ2 .Add (&ZZ2 , &ZZ2 )
XplusYsq .Add (&p .X , &p .Y )
XplusYsq .Square (&XplusYsq )
v .Y .Add (&YY , &XX )
v .Z .Subtract (&YY , &XX )
v .X .Subtract (&XplusYsq , &v .Y )
v .T .Subtract (&ZZ2 , &v .Z )
return v
}
func (v *Point ) Negate (p *Point ) *Point {
checkInitialized (p )
v .x .Negate (&p .x )
v .y .Set (&p .y )
v .z .Set (&p .z )
v .t .Negate (&p .t )
return v
}
func (v *Point ) Equal (u *Point ) int {
checkInitialized (v , u )
var t1 , t2 , t3 , t4 field .Element
t1 .Multiply (&v .x , &u .z )
t2 .Multiply (&u .x , &v .z )
t3 .Multiply (&v .y , &u .z )
t4 .Multiply (&u .y , &v .z )
return t1 .Equal (&t2 ) & t3 .Equal (&t4 )
}
func (v *projCached ) Select (a , b *projCached , cond int ) *projCached {
v .YplusX .Select (&a .YplusX , &b .YplusX , cond )
v .YminusX .Select (&a .YminusX , &b .YminusX , cond )
v .Z .Select (&a .Z , &b .Z , cond )
v .T2d .Select (&a .T2d , &b .T2d , cond )
return v
}
func (v *affineCached ) Select (a , b *affineCached , cond int ) *affineCached {
v .YplusX .Select (&a .YplusX , &b .YplusX , cond )
v .YminusX .Select (&a .YminusX , &b .YminusX , cond )
v .T2d .Select (&a .T2d , &b .T2d , cond )
return v
}
func (v *projCached ) CondNeg (cond int ) *projCached {
v .YplusX .Swap (&v .YminusX , cond )
v .T2d .Select (new (field .Element ).Negate (&v .T2d ), &v .T2d , cond )
return v
}
func (v *affineCached ) CondNeg (cond int ) *affineCached {
v .YplusX .Swap (&v .YminusX , cond )
v .T2d .Select (new (field .Element ).Negate (&v .T2d ), &v .T2d , cond )
return v
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .