mirror of
https://github.com/fumiama/go-x25519.git
synced 2026-06-05 02:00:25 +08:00
75 lines
1.7 KiB
Go
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
|
|
}
|