Skip to content

[go1.20] Updating generics overrides for crypto #1312

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
May 28, 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
58 changes: 58 additions & 0 deletions compiler/natives/src/crypto/ecdh/nist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//go:build js
// +build js

package ecdh

import (
"crypto/internal/nistec"
"io"
)

//gopherjs:purge for go1.20 without generics
type nistPoint[T any] interface{}

// temporarily replacement of `nistCurve[Point nistPoint[Point]]` for go1.20 without generics.
type nistCurve struct {
name string
newPoint func() nistec.WrappedPoint
scalarOrder []byte
}

//gopherjs:override-signature
func (c *nistCurve) String() string

//gopherjs:override-signature
func (c *nistCurve) GenerateKey(rand io.Reader) (*PrivateKey, error)

//gopherjs:override-signature
func (c *nistCurve) NewPrivateKey(key []byte) (*PrivateKey, error)

//gopherjs:override-signature
func (c *nistCurve) privateKeyToPublicKey(key *PrivateKey) *PublicKey

//gopherjs:override-signature
func (c *nistCurve) NewPublicKey(key []byte) (*PublicKey, error)

//gopherjs:override-signature
func (c *nistCurve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error)

// temporarily replacement for go1.20 without generics.
var p256 = &nistCurve{
name: "P-256",
newPoint: nistec.NewP256WrappedPoint,
scalarOrder: p256Order,
}

// temporarily replacement for go1.20 without generics.
var p384 = &nistCurve{
name: "P-384",
newPoint: nistec.NewP384WrappedPoint,
scalarOrder: p384Order,
}

// temporarily replacement for go1.20 without generics.
var p521 = &nistCurve{
name: "P-521",
newPoint: nistec.NewP521WrappedPoint,
scalarOrder: p521Order,
}
98 changes: 98 additions & 0 deletions compiler/natives/src/crypto/ecdsa/ecdsa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//go:build js
// +build js

package ecdsa

import (
"crypto/elliptic"
"crypto/internal/bigmod"
"crypto/internal/nistec"
"io"
"math/big"
)

//gopherjs:override-signature
func generateNISTEC(c *nistCurve, rand io.Reader) (*PrivateKey, error)

//gopherjs:override-signature
func randomPoint(c *nistCurve, rand io.Reader) (k *bigmod.Nat, p nistec.WrappedPoint, err error)

//gopherjs:override-signature
func signNISTEC(c *nistCurve, priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error)

//gopherjs:override-signature
func inverse(c *nistCurve, kInv, k *bigmod.Nat)

//gopherjs:override-signature
func hashToNat(c *nistCurve, e *bigmod.Nat, hash []byte)

//gopherjs:override-signature
func verifyNISTEC(c *nistCurve, pub *PublicKey, hash, sig []byte) bool

//gopherjs:purge for go1.20 without generics
type nistPoint[T any] interface{}

// temporarily replacement of `nistCurve[Point nistPoint[Point]]` for go1.20 without generics.
type nistCurve struct {
newPoint func() nistec.WrappedPoint
curve elliptic.Curve
N *bigmod.Modulus
nMinus2 []byte
}

//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, err error)

var _p224 *nistCurve

func p224() *nistCurve {
p224Once.Do(func() {
_p224 = &nistCurve{
newPoint: nistec.NewP224WrappedPoint,
}
precomputeParams(_p224, elliptic.P224())
})
return _p224
}

var _p256 *nistCurve

func p256() *nistCurve {
p256Once.Do(func() {
_p256 = &nistCurve{
newPoint: nistec.NewP256WrappedPoint,
}
precomputeParams(_p256, elliptic.P256())
})
return _p256
}

var _p384 *nistCurve

func p384() *nistCurve {
p384Once.Do(func() {
_p384 = &nistCurve{
newPoint: nistec.NewP384WrappedPoint,
}
precomputeParams(_p384, elliptic.P384())
})
return _p384
}

var _p521 *nistCurve

func p521() *nistCurve {
p521Once.Do(func() {
_p521 = &nistCurve{
newPoint: nistec.NewP521WrappedPoint,
}
precomputeParams(_p521, elliptic.P521())
})
return _p521
}

//gopherjs:override-signature
func precomputeParams(c *nistCurve, curve elliptic.Curve)
12 changes: 12 additions & 0 deletions compiler/natives/src/crypto/ecdsa/ecdsa_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//go:build js
// +build js

package ecdsa

import "testing"

//gopherjs:override-signature
func testRandomPoint(t *testing.T, c *nistCurve)

//gopherjs:override-signature
func testHashToNat(t *testing.T, c *nistCurve)
3 changes: 3 additions & 0 deletions compiler/natives/src/crypto/internal/boring/bcache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ func (c *Cache) Put(k, v unsafe.Pointer) {}
//gopherjs:purge
func (c *Cache) table() *[cacheSize]unsafe.Pointer

//gopherjs:purge
type cacheTable struct{}

//gopherjs:purge
type cacheEntry struct{}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package bcache

import "testing"

var registeredCache Cache

func TestCache(t *testing.T) {
t.Skip(`This test uses runtime.GC(), which GopherJS doesn't support`)
}
36 changes: 18 additions & 18 deletions compiler/natives/src/crypto/internal/nistec/nistec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,52 +18,52 @@ 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())
testEquivalents(t, nistec.NewP224WrappedPoint, elliptic.P224())
})
t.Run("P256", func(t *testing.T) {
testEquivalents(t, nistec.NewP256WrappedPoint, nistec.NewP256WrappedGenerator, elliptic.P256())
testEquivalents(t, nistec.NewP256WrappedPoint, elliptic.P256())
})
t.Run("P384", func(t *testing.T) {
testEquivalents(t, nistec.NewP384WrappedPoint, nistec.NewP384WrappedGenerator, elliptic.P384())
testEquivalents(t, nistec.NewP384WrappedPoint, elliptic.P384())
})
t.Run("P521", func(t *testing.T) {
testEquivalents(t, nistec.NewP521WrappedPoint, nistec.NewP521WrappedGenerator, elliptic.P521())
testEquivalents(t, nistec.NewP521WrappedPoint, elliptic.P521())
})
}

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

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

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

func BenchmarkScalarMult(b *testing.B) {
b.Run("P224", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP224WrappedGenerator(), 28)
benchmarkScalarMult(b, nistec.NewP224WrappedPoint().SetGenerator(), 28)
})
b.Run("P256", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP256WrappedGenerator(), 32)
benchmarkScalarMult(b, nistec.NewP256WrappedPoint().SetGenerator(), 32)
})
b.Run("P384", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP384WrappedGenerator(), 48)
benchmarkScalarMult(b, nistec.NewP384WrappedPoint().SetGenerator(), 48)
})
b.Run("P521", func(b *testing.B) {
benchmarkScalarMult(b, nistec.NewP521WrappedGenerator(), 66)
benchmarkScalarMult(b, nistec.NewP521WrappedPoint().SetGenerator(), 66)
})
}

Expand All @@ -72,16 +72,16 @@ func benchmarkScalarMult(b *testing.B, p nistec.WrappedPoint, scalarSize int)

func BenchmarkScalarBaseMult(b *testing.B) {
b.Run("P224", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP224WrappedGenerator(), 28)
benchmarkScalarBaseMult(b, nistec.NewP224WrappedPoint().SetGenerator(), 28)
})
b.Run("P256", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP256WrappedGenerator(), 32)
benchmarkScalarBaseMult(b, nistec.NewP256WrappedPoint().SetGenerator(), 32)
})
b.Run("P384", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP384WrappedGenerator(), 48)
benchmarkScalarBaseMult(b, nistec.NewP384WrappedPoint().SetGenerator(), 48)
})
b.Run("P521", func(b *testing.B) {
benchmarkScalarBaseMult(b, nistec.NewP521WrappedGenerator(), 66)
benchmarkScalarBaseMult(b, nistec.NewP521WrappedPoint().SetGenerator(), 66)
})
}

Expand Down
35 changes: 27 additions & 8 deletions compiler/natives/src/crypto/internal/nistec/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

package nistec

// temporarily replacement of `nistPoint[T any]` for go1.20 without generics.
type WrappedPoint interface {
SetGenerator() WrappedPoint
Bytes() []byte
BytesX() ([]byte, error)
SetBytes(b []byte) (WrappedPoint, error)
Add(w1, w2 WrappedPoint) WrappedPoint
Double(w1 WrappedPoint) WrappedPoint
Expand All @@ -24,14 +27,18 @@ func NewP224WrappedPoint() WrappedPoint {
return wrapP224(NewP224Point())
}

func NewP224WrappedGenerator() WrappedPoint {
return wrapP224(NewP224Generator())
func (w p224Wrapper) SetGenerator() WrappedPoint {
return wrapP224(w.point.SetGenerator())
}

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

func (w p224Wrapper) BytesX() ([]byte, error) {
return w.point.BytesX()
}

func (w p224Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP224(p), err
Expand Down Expand Up @@ -67,14 +74,18 @@ func NewP256WrappedPoint() WrappedPoint {
return wrapP256(NewP256Point())
}

func NewP256WrappedGenerator() WrappedPoint {
return wrapP256(NewP256Generator())
func (w p256Wrapper) SetGenerator() WrappedPoint {
return wrapP256(w.point.SetGenerator())
}

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

func (w p256Wrapper) BytesX() ([]byte, error) {
return w.point.BytesX()
}

func (w p256Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP256(p), err
Expand Down Expand Up @@ -110,14 +121,18 @@ func NewP521WrappedPoint() WrappedPoint {
return wrapP521(NewP521Point())
}

func NewP521WrappedGenerator() WrappedPoint {
return wrapP521(NewP521Generator())
func (w p521Wrapper) SetGenerator() WrappedPoint {
return wrapP521(w.point.SetGenerator())
}

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

func (w p521Wrapper) BytesX() ([]byte, error) {
return w.point.BytesX()
}

func (w p521Wrapper) SetBytes(b []byte) (WrappedPoint, error) {
p, err := w.point.SetBytes(b)
return wrapP521(p), err
Expand Down Expand Up @@ -153,14 +168,18 @@ func NewP384WrappedPoint() WrappedPoint {
return wrapP384(NewP384Point())
}

func NewP384WrappedGenerator() WrappedPoint {
return wrapP384(NewP384Generator())
func (w p384Wrapper) SetGenerator() WrappedPoint {
return wrapP384(w.point.SetGenerator())
}

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

func (w p384Wrapper) BytesX() ([]byte, error) {
return w.point.BytesX()
}

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