Last active
July 15, 2020 09:59
-
-
Save crossle/ea063aa77f879216cc664792d7022700 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/ed25519" | |
"crypto/rand" | |
"crypto/sha512" | |
"encoding/hex" | |
"fmt" | |
"math/big" | |
"golang.org/x/crypto/curve25519" | |
) | |
// https://github.com/FiloSottile/age/blob/189041b668629795593766bcb8d3f70ee248b842/agessh/agessh.go#L294 | |
func main() { | |
pub, priv, err := ed25519.GenerateKey(rand.Reader) | |
a := hex.EncodeToString(pub) | |
fmt.Println(a) | |
b := hex.EncodeToString(priv) | |
fmt.Println(b) | |
fmt.Println(err) | |
c := hex.EncodeToString(ed25519PublicKeyToCurve25519(pub)) | |
fmt.Println(c) | |
d := hex.EncodeToString(ed25519PrivateKeyToCurve25519(priv)) | |
fmt.Println(d) | |
} | |
var curve25519P, _ = new(big.Int).SetString("57896044618658097711785492504343953926634992332820282019728792003956564819949", 10) | |
func ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte { | |
h := sha512.New() | |
h.Write(pk.Seed()) | |
out := h.Sum(nil) | |
return out[:curve25519.ScalarSize] | |
} | |
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 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment