8 changed files with 127 additions and 29 deletions
@ -1,22 +1,95 @@ |
|||
package utils |
|||
|
|||
import ( |
|||
"github.com/agl/ed25519/extra25519" |
|||
"crypto/sha512" |
|||
"golang.org/x/crypto/curve25519" |
|||
"golang.org/x/crypto/ed25519" |
|||
"math/big" |
|||
) |
|||
|
|||
// EDH implements diffie hellman using curve25519 keys derived from ed25519 keys
|
|||
// NOTE: This uses a 3rd party library extra25519 as the key conversion is not in the core golang lib
|
|||
// as such this definitely needs further review.
|
|||
func EDH(privateKey ed25519.PrivateKey, remotePublicKey ed25519.PublicKey) [32]byte { |
|||
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 secret, curve25519priv, curve25519pub [32]byte |
|||
extra25519.PrivateKeyToCurve25519(&curve25519priv, &privKeyBytes) |
|||
extra25519.PublicKeyToCurve25519(&curve25519pub, &remotePubKeyBytes) |
|||
curve25519.ScalarMult(&secret, &curve25519priv, &curve25519pub) |
|||
return secret |
|||
var curve25519priv [32]byte |
|||
|
|||
PrivateKeyToCurve25519(&curve25519priv, &privKeyBytes) |
|||
curve25519pub := ed25519PublicKeyToCurve25519(remotePublicKey) |
|||
secret, err := curve25519.X25519(curve25519priv[:], curve25519pub[:]) |
|||
return secret, err |
|||
} |
|||
|
|||
// https://github.com/FiloSottile/age/blob/master/internal/age/ssh.go#L174
|
|||
// Copyright 2019 Google LLC
|
|||
//
|
|||
//Redistribution and use in source and binary forms, with or without
|
|||
//modification, are permitted provided that the following conditions are
|
|||
//met:
|
|||
//
|
|||
// * Redistributions of source code must retain the above copyright
|
|||
//notice, this list of conditions and the following disclaimer.
|
|||
// * Redistributions in binary form must reproduce the above
|
|||
//copyright notice, this list of conditions and the following disclaimer
|
|||
//in the documentation and/or other materials provided with the
|
|||
//distribution.
|
|||
// * Neither the name of Google LLC nor the names of its
|
|||
//contributors may be used to endorse or promote products derived from
|
|||
//this software without specific prior written permission.
|
|||
//
|
|||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
//A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
//OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
//LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
//DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
//THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
//OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
var curve25519P, _ = new(big.Int).SetString("57896044618658097711785492504343953926634992332820282019728792003956564819949", 10) |
|||
|
|||
func ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) []byte { |
|||
// ed25519.PublicKey is a little endian representation of the y-coordinate,
|
|||
// with the most significant bit set based on the sign of the x-coordinate.
|
|||
bigEndianY := make([]byte, ed25519.PublicKeySize) |
|||
for i, b := range pk { |
|||
bigEndianY[ed25519.PublicKeySize-i-1] = b |
|||
} |
|||
bigEndianY[0] &= 0b0111_1111 |
|||
|
|||
// The Montgomery u-coordinate is derived through the bilinear map
|
|||
//
|
|||
// u = (1 + y) / (1 - y)
|
|||
//
|
|||
// See https://blog.filippo.io/using-ed25519-keys-for-encryption.
|
|||
y := new(big.Int).SetBytes(bigEndianY) |
|||
denom := big.NewInt(1) |
|||
denom.ModInverse(denom.Sub(denom, y), curve25519P) // 1 / (1 - y)
|
|||
u := y.Mul(y.Add(y, big.NewInt(1)), denom) |
|||
u.Mod(u, curve25519P) |
|||
|
|||
out := make([]byte, curve25519.PointSize) |
|||
uBytes := u.Bytes() |
|||
for i, b := range uBytes { |
|||
out[len(uBytes)-i-1] = b |
|||
} |
|||
|
|||
return out |
|||
} |
|||
|
|||
// 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) |
|||
} |
|||
|
Loading…
Reference in new issue