Skip to content

[go1.19] Updating natives #1262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions compiler/natives/src/crypto/elliptic/nistec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//go:build js
// +build js

package elliptic

import (
"crypto/internal/nistec"
"math/big"
)

// nistPoint uses generics so must be removed for generic-less GopherJS.
// All the following code changes in this file are to make p224, p256,
// p521, and p384 still function correctly without this generic struct.
//
//gopherjs:purge for go1.19 without generics
type nistPoint[T any] interface{}

// nistCurve replaces the generics with a version using the wrappedPoint
// interface, then update all the method signatures to also use wrappedPoint.
type nistCurve struct {
newPoint func() nistec.WrappedPoint
params *CurveParams
}

//gopherjs:override-signature
func (curve *nistCurve) Params() *CurveParams

//gopherjs:override-signature
func (curve *nistCurve) IsOnCurve(x, y *big.Int) bool

//gopherjs:override-signature
func (curve *nistCurve) pointFromAffine(x, y *big.Int) (p nistec.WrappedPoint, err error)

//gopherjs:override-signature
func (curve *nistCurve) pointToAffine(p nistec.WrappedPoint) (x, y *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) normalizeScalar(scalar []byte) []byte

//gopherjs:override-signature
func (curve *nistCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) CombinedMult(Px, Py *big.Int, s1, s2 []byte) (x, y *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) Unmarshal(data []byte) (x, y *big.Int)

//gopherjs:override-signature
func (curve *nistCurve) UnmarshalCompressed(data []byte) (x, y *big.Int)

var p224 = &nistCurve{
newPoint: nistec.NewP224WrappedPoint,
}

type p256Curve struct {
nistCurve
}

var p256 = &p256Curve{
nistCurve: nistCurve{
newPoint: nistec.NewP256WrappedPoint,
},
}

var p521 = &nistCurve{
newPoint: nistec.NewP521WrappedPoint,
}

var p384 = &nistCurve{
newPoint: nistec.NewP384WrappedPoint,
}
42 changes: 42 additions & 0 deletions compiler/natives/src/crypto/internal/boring/bbig/big.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//go:build js
// +build js

package bbig

import (
"crypto/internal/boring"
"math/big"
)

func Enc(b *big.Int) boring.BigInt {
if b == nil {
return nil
}
x := b.Bits()
if len(x) == 0 {
return boring.BigInt{}
}
// Replacing original which uses unsafe:
// return unsafe.Slice((*uint)(&x[0]), len(x))
b2 := make(boring.BigInt, len(x))
for i, w := range x {
b2[i] = uint(w)
}
return b2
}

func Dec(b boring.BigInt) *big.Int {
if b == nil {
return nil
}
if len(b) == 0 {
return new(big.Int)
}
// Replacing original which uses unsafe:
//x := unsafe.Slice((*big.Word)(&b[0]), len(b))
x := make([]big.Word, len(b))
for i, w := range b {
x[i] = big.Word(w)
}
return new(big.Int).SetBits(x)
}
88 changes: 88 additions & 0 deletions compiler/natives/src/crypto/internal/nistec/nistec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//go:build js
// +build js

package nistec_test

import (
"crypto/elliptic"
"testing"
)

func TestAllocations(t *testing.T) {
t.Skip("testing.AllocsPerRun not supported in GopherJS")
}

//gopherjs:purge
type nistPoint[T any] interface{}

func TestEquivalents(t *testing.T) {
t.Run("P224", func(t *testing.T) {
testEquivalents(t, nistec.NewP224WrappedPoint, nistec.NewP224WrappedGenerator, elliptic.P224())
})
t.Run("P256", func(t *testing.T) {
testEquivalents(t, nistec.NewP256WrappedPoint, nistec.NewP256WrappedGenerator, elliptic.P256())
})
t.Run("P384", func(t *testing.T) {
testEquivalents(t, nistec.NewP384WrappedPoint, nistec.NewP384WrappedGenerator, elliptic.P384())
})
t.Run("P521", func(t *testing.T) {
testEquivalents(t, nistec.NewP521WrappedPoint, nistec.NewP521WrappedGenerator, elliptic.P521())
})
}

//gopherjs:override-signature
func testEquivalents(t *testing.T, newPoint, newGenerator func() WrappedPoint, c elliptic.Curve) {}

func TestScalarMult(t *testing.T) {
t.Run("P224", func(t *testing.T) {
testScalarMult(t, nistec.NewP224WrappedPoint, nistec.NewP224WrappedGenerator, elliptic.P224())
})
t.Run("P256", func(t *testing.T) {
testScalarMult(t, nistec.NewP256WrappedPoint, nistec.NewP256WrappedGenerator, elliptic.P256())
})
t.Run("P384", func(t *testing.T) {
testScalarMult(t, nistec.NewP384WrappedPoint, nistec.NewP384WrappedGenerator, elliptic.P384())
})
t.Run("P521", func(t *testing.T) {
testScalarMult(t, nistec.NewP521WrappedPoint, nistec.NewP521WrappedGenerator, elliptic.P521())
})
}

//gopherjs:override-signature
func testScalarMult(t *testing.T, newPoint, newGenerator func() WrappedPoint, c elliptic.Curve)

func BenchmarkScalarMult(b *testing.B) {
b.Run("P224", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP224WrappedGenerator(), 28)
})
b.Run("P256", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP256GWrappedenerator(), 32)
})
b.Run("P384", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP384WrappedGenerator(), 48)
})
b.Run("P521", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP521WrappedGenerator(), 66)
})
}

//gopherjs:override-signature
func benchmarkScalarMult(b *testing.B, p WrappedPoint, scalarSize int)

func BenchmarkScalarBaseMult(b *testing.B) {
b.Run("P224", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP22Wrapped4Generator(), 28)
})
b.Run("P256", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP256WrappedGenerator(), 32)
})
b.Run("P384", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP384WrappedGenerator(), 48)
})
b.Run("P521", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP521GWrappedenerator(), 66)
})
}

//gopherjs:override-signature
func benchmarkScalarBaseMult(b *testing.B, p WrappedPoint, scalarSize int)
185 changes: 185 additions & 0 deletions compiler/natives/src/crypto/internal/nistec/wrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
//go:build js
// +build js

package nistec

type WrappedPoint interface {
Bytes() []byte
SetBytes(b []byte) (WrappedPoint, error)
Add(w1, w2 WrappedPoint) WrappedPoint
Double(w1 WrappedPoint) WrappedPoint
ScalarMult(w1 WrappedPoint, scalar []byte) (WrappedPoint, error)
ScalarBaseMult(scalar []byte) (WrappedPoint, error)
}

type p224Wrapper struct {
point *P224Point
}

func wrapP224(point *P224Point) WrappedPoint {
return p224Wrapper{point: point}
}

func NewP224WrappedPoint() WrappedPoint {
return wrapP224(NewP224Point())
}

func NewP224WrappedGenerator() WrappedPoint {
return wrapP224(NewP224Generator())
}

func (w p224Wrapper) Bytes() []byte {
return w.point.Bytes()
}

func (w p224Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP224(p), err
}

func (w p224Wrapper) Add(w1, w2 WrappedPoint) WrappedPoint {
return wrapP224(w.point.Add(w1.(p224Wrapper).point, w2.(p224Wrapper).point))
}

func (w p224Wrapper) Double(w1 WrappedPoint) WrappedPoint {
return wrapP224(w.point.Double(w1.(p224Wrapper).point))
}

func (w p224Wrapper) ScalarMult(w1 WrappedPoint, scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarMult(w1.(p224Wrapper).point, scalar)
return wrapP224(p), err
}

func (w p224Wrapper) ScalarBaseMult(scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarBaseMult(scalar)
return wrapP224(p), err
}

type p256Wrapper struct {
point *P256Point
}

func wrapP256(point *P256Point) WrappedPoint {
return p256Wrapper{point: point}
}

func NewP256WrappedPoint() WrappedPoint {
return wrapP256(NewP256Point())
}

func NewP256WrappedGenerator() WrappedPoint {
return wrapP256(NewP256Generator())
}

func (w p256Wrapper) Bytes() []byte {
return w.point.Bytes()
}

func (w p256Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP256(p), err
}

func (w p256Wrapper) Add(w1, w2 WrappedPoint) WrappedPoint {
return wrapP256(w.point.Add(w1.(p256Wrapper).point, w2.(p256Wrapper).point))
}

func (w p256Wrapper) Double(w1 WrappedPoint) WrappedPoint {
return wrapP256(w.point.Double(w1.(p256Wrapper).point))
}

func (w p256Wrapper) ScalarMult(w1 WrappedPoint, scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarMult(w1.(p256Wrapper).point, scalar)
return wrapP256(p), err
}

func (w p256Wrapper) ScalarBaseMult(scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarBaseMult(scalar)
return wrapP256(p), err
}

type p521Wrapper struct {
point *P521Point
}

func wrapP521(point *P521Point) WrappedPoint {
return p521Wrapper{point: point}
}

func NewP521WrappedPoint() WrappedPoint {
return wrapP521(NewP521Point())
}

func NewP521WrappedGenerator() WrappedPoint {
return wrapP521(NewP521Generator())
}

func (w p521Wrapper) Bytes() []byte {
return w.point.Bytes()
}

func (w p521Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP521(p), err
}

func (w p521Wrapper) Add(w1, w2 WrappedPoint) WrappedPoint {
return wrapP521(w.point.Add(w1.(p521Wrapper).point, w2.(p521Wrapper).point))
}

func (w p521Wrapper) Double(w1 WrappedPoint) WrappedPoint {
return wrapP521(w.point.Double(w1.(p521Wrapper).point))
}

func (w p521Wrapper) ScalarMult(w1 WrappedPoint, scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarMult(w1.(p521Wrapper).point, scalar)
return wrapP521(p), err
}

func (w p521Wrapper) ScalarBaseMult(scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarBaseMult(scalar)
return wrapP521(p), err
}

type p384Wrapper struct {
point *P384Point
}

func wrapP384(point *P384Point) WrappedPoint {
return p384Wrapper{point: point}
}

func NewP384WrappedPoint() WrappedPoint {
return wrapP384(NewP384Point())
}

func NewP384WrappedGenerator() WrappedPoint {
return wrapP384(NewP384Generator())
}

func (w p384Wrapper) Bytes() []byte {
return w.point.Bytes()
}

func (w p384Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP384(p), err
}

func (w p384Wrapper) Add(w1, w2 WrappedPoint) WrappedPoint {
return wrapP384(w.point.Add(w1.(p384Wrapper).point, w2.(p384Wrapper).point))
}

func (w p384Wrapper) Double(w1 WrappedPoint) WrappedPoint {
return wrapP384(w.point.Double(w1.(p384Wrapper).point))
}

func (w p384Wrapper) ScalarMult(w1 WrappedPoint, scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarMult(w1.(p384Wrapper).point, scalar)
return wrapP384(p), err
}

func (w p384Wrapper) ScalarBaseMult(scalar []byte) (WrappedPoint, error) {
p, err := w.point.ScalarBaseMult(scalar)
return wrapP384(p), err
}
Loading