forked from cwtch.im/tapir
51 lines
1.5 KiB
Go
51 lines
1.5 KiB
Go
package utils
|
|
|
|
import (
|
|
"crypto/sha512"
|
|
"filippo.io/edwards25519"
|
|
"golang.org/x/crypto/curve25519"
|
|
"golang.org/x/crypto/ed25519"
|
|
)
|
|
|
|
// EDH implements diffie hellman using curve25519 keys derived from ed25519 keys
|
|
func EDH(privateKey ed25519.PrivateKey, remotePublicKey ed25519.PublicKey) ([]byte, error) {
|
|
var privKeyBytes [64]byte
|
|
var remotePubKeyBytes [32]byte
|
|
copy(privKeyBytes[:], privateKey[:])
|
|
copy(remotePubKeyBytes[:], remotePublicKey[:])
|
|
var curve25519priv [32]byte
|
|
|
|
PrivateKeyToCurve25519(&curve25519priv, &privKeyBytes)
|
|
remoteCurve25519pub, err := ed25519PublicKeyToCurve25519New(remotePublicKey)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
secret, err := curve25519.X25519(curve25519priv[:], remoteCurve25519pub[:])
|
|
return secret, err
|
|
}
|
|
|
|
// reproduced from https://github.com/FiloSottile/age/blob/main/agessh/agessh.go#L190
|
|
func ed25519PublicKeyToCurve25519New(pk ed25519.PublicKey) ([]byte, error) {
|
|
// See https://blog.filippo.io/using-ed25519-keys-for-encryption and
|
|
// https://pkg.go.dev/filippo.io/edwards25519#Point.BytesMontgomery.
|
|
p, err := new(edwards25519.Point).SetBytes(pk)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return p.BytesMontgomery(), nil
|
|
}
|
|
|
|
// PrivateKeyToCurve25519 converts an ed25519 private key into a corresponding
|
|
// curve25519 private key
|
|
func PrivateKeyToCurve25519(curve25519Private *[32]byte, privateKey *[64]byte) {
|
|
h := sha512.New()
|
|
h.Write(privateKey[:32])
|
|
digest := h.Sum(nil)
|
|
|
|
digest[0] &= 248
|
|
digest[31] &= 127
|
|
digest[31] |= 64
|
|
|
|
copy(curve25519Private[:], digest)
|
|
}
|