diff --git a/crypto/curve_25519.go b/crypto/curve_25519.go new file mode 100644 index 000000000..f814a0c93 --- /dev/null +++ b/crypto/curve_25519.go @@ -0,0 +1,45 @@ +package crypto + +import ( + "crypto/rand" + "errors" + + "golang.org/x/crypto/curve25519" +) + +// KeyExchange manages the exchange of keys +type curve25519KEX struct { + secret [32]byte + public [32]byte +} + +var _ KeyExchange = &curve25519KEX{} + +// NewCurve25519KEX creates a new KeyExchange using Curve25519, see https://cr.yp.to/ecdh.html +func NewCurve25519KEX() KeyExchange { + c := &curve25519KEX{} + if n, err := rand.Reader.Read(c.secret[:]); n != 32 || err != nil { + panic("Curve25519: could not create private key") + } + // See https://cr.yp.to/ecdh.html + c.secret[0] &= 248 + c.secret[31] &= 127 + c.secret[31] |= 64 + curve25519.ScalarBaseMult(&c.public, &c.secret) + return c +} + +func (c *curve25519KEX) PublicKey() []byte { + return c.public[:] +} + +func (c *curve25519KEX) CalculateSharedKey(otherPublic []byte) ([]byte, error) { + if len(otherPublic) != 32 { + return nil, errors.New("Curve25519: expected public key of 32 byte") + } + var res [32]byte + var otherPublicArray [32]byte + copy(otherPublicArray[:], otherPublic) + curve25519.ScalarMult(&res, &c.secret, &otherPublicArray) + return res[:], nil +} diff --git a/crypto/curve_25519_test.go b/crypto/curve_25519_test.go new file mode 100644 index 000000000..04736cd2f --- /dev/null +++ b/crypto/curve_25519_test.go @@ -0,0 +1,18 @@ +package crypto + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("ProofRsa", func() { + It("works", func() { + a := NewCurve25519KEX() + b := NewCurve25519KEX() + sA, err := a.CalculateSharedKey(b.PublicKey()) + Expect(err).ToNot(HaveOccurred()) + sB, err := b.CalculateSharedKey(a.PublicKey()) + Expect(err).ToNot(HaveOccurred()) + Expect(sA).To(Equal(sB)) + }) +}) diff --git a/crypto/key_exchange.go b/crypto/key_exchange.go new file mode 100644 index 000000000..d240b9c90 --- /dev/null +++ b/crypto/key_exchange.go @@ -0,0 +1,7 @@ +package crypto + +// KeyExchange manages the exchange of keys +type KeyExchange interface { + PublicKey() []byte + CalculateSharedKey(otherPublic []byte) ([]byte, error) +}