1
0
mirror of https://github.com/fumiama/go-x25519.git synced 2026-06-05 02:00:25 +08:00
Files
go-x25519/x25519.go
2021-10-25 20:58:36 +08:00

75 lines
1.7 KiB
Go

// Package x25519 implements Elliptic Curve Diffie-Hellman (ECDH) function over Curve25519.
// Details at https://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748
package x25519
import (
"crypto/rand"
"io"
"sync"
"unsafe"
"golang.org/x/crypto/curve25519"
)
// KEYSZ is the size of keys in bytes used in this package.
const KEYSZ = 32
// 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
}
// 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 *Curve) Public() *PublicKey {
if !k.ispkset {
sk := k.sk
var pk PublicKey
curve25519.ScalarBaseMult(&pk, &sk)
k.pkmu.Lock()
if !k.ispkset {
k.pk = pk
}
k.pkmu.Unlock()
k.ispkset = true
}
return &k.pk
}
// Shared computes the shared secret between our secret key and peer's public key.
func (k *Curve) Shared(peer *PublicKey) ([]byte, error) {
return curve25519.X25519(k.sk[:], (*peer)[:])
}
// 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
}
// New generates a secret key using entropy from random, or crypto/rand.Reader
// if random is nil.
func New(random io.Reader) (k *Curve, err error) {
if random == nil {
random = rand.Reader
}
k = new(Curve)
_, err = random.Read(k.sk[:])
return
}