From f5158ef0fd978be4eb2026fc46fb66f1e850882c Mon Sep 17 00:00:00 2001 From: fumiama Date: Mon, 25 Oct 2021 20:58:36 +0800 Subject: [PATCH] bump to go 1.16 --- go.mod | 5 ++ go.sum | 8 +++ x25519.go | 133 ++++++++++++++++--------------------------------- x25519_test.go | 44 ++++++++-------- 4 files changed, 76 insertions(+), 114 deletions(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f84a072 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/fumiama/go-x25519 + +go 1.16 + +require golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..814b1a3 --- /dev/null +++ b/go.sum @@ -0,0 +1,8 @@ +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/x25519.go b/x25519.go index 719bf71..2e32b23 100644 --- a/x25519.go +++ b/x25519.go @@ -5,117 +5,70 @@ package x25519 import ( "crypto/rand" "io" + "sync" + "unsafe" - "github.com/agl/ed25519/extra25519" "golang.org/x/crypto/curve25519" ) -// KeySize is the size of keys in bytes used in this package. -const KeySize = 32 +// KEYSZ is the size of keys in bytes used in this package. +const KEYSZ = 32 -// SecretKey is the type of Curve25519 secret keys. -type SecretKey struct { - sk []byte - pk PublicKey - ur []byte // uniform representative of pk +// PublicKey is the type of Curve25519 public keys. +type PublicKey = [KEYSZ]byte + +// PrivateKey is the type of Curve25519 secret keys. +type PrivateKey = [KEYSZ]byte + +// Curve is the type of Curve25519 secret keys. +type Curve struct { + sk PrivateKey + pk PublicKey + ispkset bool + pkmu sync.Mutex } -// Bytes returns the secret key as a byte slice. -func (k *SecretKey) Bytes() []byte { return k.sk } +// Private returns the secret key as a byte array pointer. +func (k *Curve) Private() *PrivateKey { return &k.sk } // Public returns the PublicKey corresponding to the secret key. -func (k *SecretKey) Public() PublicKey { - if k.pk == nil { - var pk, sk [32]byte - copy(sk[:], k.sk) +func (k *Curve) Public() *PublicKey { + if !k.ispkset { + sk := k.sk + var pk PublicKey curve25519.ScalarBaseMult(&pk, &sk) - k.pk = pk[:] - } - return k.pk -} - -// PublicUniform returns the uniform representative of the public key corresponding to the secret key, or nil -// if the public key does not have a uniform representative. -func (k *SecretKey) PublicUniform() UniformRepresentative { - if k.ur == nil { - var sk, pk, ur [32]byte - copy(sk[:], k.sk) - if extra25519.ScalarBaseMult(&pk, &ur, &sk) { - k.pk = pk[:] - k.ur = ur[:] + k.pkmu.Lock() + if !k.ispkset { + k.pk = pk } + k.pkmu.Unlock() + k.ispkset = true } - return k.ur + return &k.pk } // Shared computes the shared secret between our secret key and peer's public key. -func (k *SecretKey) Shared(peer PublicKey) []byte { - var shared, sk, pk [32]byte - copy(sk[:], k.sk) - copy(pk[:], peer) - curve25519.ScalarMult(&shared, &sk, &pk) - return shared[:] +func (k *Curve) Shared(peer *PublicKey) ([]byte, error) { + return curve25519.X25519(k.sk[:], (*peer)[:]) } -// SharedUniform computes the shared secret between our secret key and peer public key's uniform representative. -func (k *SecretKey) SharedUniform(peer UniformRepresentative) []byte { - var shared, pk, sk, ur [32]byte - copy(ur[:], peer) - copy(sk[:], k.sk) - extra25519.RepresentativeToPublicKey(&pk, &ur) - curve25519.ScalarMult(&shared, &sk, &pk) - return shared[:] +// Get creates a PrivateKey from []byte sk and len(sk) must be 32. +func Get(sk []byte) *Curve { + if len(sk) == KEYSZ { + k := new(Curve) + k.sk = *(*PrivateKey)(*(*unsafe.Pointer)(unsafe.Pointer(&sk))) + return k + } + return nil } -// NewSecretKey creates a SecretKey from byte slice sk and len(sk) must be 32. -func NewSecretKey(sk []byte) *SecretKey { - k := new(SecretKey) - k.sk = sk - return k -} - -// GenerateKey generates a secret key using entropy from random, or crypto/rand.Reader +// New generates a secret key using entropy from random, or crypto/rand.Reader // if random is nil. -func GenerateKey(random io.Reader) (*SecretKey, error) { +func New(random io.Reader) (k *Curve, err error) { if random == nil { random = rand.Reader } - k := new(SecretKey) - k.sk = make([]byte, 32) - _, err := io.ReadFull(random, k.sk) - return k, err + k = new(Curve) + _, err = random.Read(k.sk[:]) + return } - -// GenerateKeyUniform generates a secret key whose corresponding public key has a uniform representative -// using entropy from random, or crypto/rand.Reader if random is nil. -func GenerateKeyUniform(random io.Reader) (*SecretKey, error) { - if random == nil { - random = rand.Reader - } - var pk, sk, ur [32]byte - for ok := false; !ok; ok = extra25519.ScalarBaseMult(&pk, &ur, &sk) { - if _, err := io.ReadFull(random, sk[:]); err != nil { - return nil, err - } - } - k := new(SecretKey) - k.sk = sk[:] - k.pk = pk[:] - k.ur = ur[:] - return k, nil -} - -// UniformRepresentative is the type of Curve25519 public key uniform representatives. -// See https://www.imperialviolet.org/2013/12/25/elligator.html -type UniformRepresentative []byte - -// Public returns the curve25519 public key corresponding to the uniform presentative. -func (u UniformRepresentative) Public() PublicKey { - var pk, ur [32]byte - copy(ur[:], u) - extra25519.RepresentativeToPublicKey(&pk, &ur) - return pk[:] -} - -// PublicKey is the type of Curve25519 public keys. -type PublicKey []byte diff --git a/x25519_test.go b/x25519_test.go index bd9183b..dff75be 100644 --- a/x25519_test.go +++ b/x25519_test.go @@ -21,7 +21,7 @@ func TestStardardKey(t *testing.T) { t.Fatal(err) } - ask := NewSecretKey(askhex) + ask := Get(askhex) apk := ask.Public() if alicePK != hex.EncodeToString(apk[:]) { t.Fatal("public key failed") @@ -32,14 +32,20 @@ func TestStardardKey(t *testing.T) { t.Fatal(err) } - bsk := NewSecretKey(bskhex) + bsk := Get(bskhex) bpk := bsk.Public() if bobPK != hex.EncodeToString(bpk[:]) { t.Fatal("public key failed") } - s1 := ask.Shared(bpk) - s2 := bsk.Shared(apk) + s1, err := ask.Shared(bpk) + if err != nil { + t.Fatal(err) + } + s2, err := bsk.Shared(apk) + if err != nil { + t.Fatal(err) + } if !bytes.Equal(s1, s2) { t.Fatal("shared secret failed") } @@ -50,28 +56,18 @@ func TestStardardKey(t *testing.T) { func TestGenerateKey(t *testing.T) { for i := 0; i < 100; i++ { - ourSK, _ := GenerateKey(nil) - theirSK, _ := GenerateKey(nil) - s1 := ourSK.Shared(theirSK.Public()) - s2 := theirSK.Shared(ourSK.Public()) + ourSK, _ := New(nil) + theirSK, _ := New(nil) + s1, err := ourSK.Shared(theirSK.Public()) + if err != nil { + t.Fatal(err) + } + s2, err := theirSK.Shared(ourSK.Public()) + if err != nil { + t.Fatal(err) + } if !bytes.Equal(s1, s2) { t.Fatal("computed shared secrets differs") } } } - -func TestUniformRepresentative(t *testing.T) { - - for i := 0; i < 1; i++ { - k, _ := GenerateKey(nil) - sk, _ := GenerateKeyUniform(nil) - pk := sk.Public() - ur := sk.PublicUniform() - if !bytes.Equal(ur.Public(), pk) { - t.Fatal("public key and its uniform representative do not match") - } - if !bytes.Equal(k.Shared(sk.Public()), k.SharedUniform(sk.PublicUniform())) { - t.Fatalf("shared secrets do not match") - } - } -}