98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
package protocol
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"crypto/sha512"
|
|
"math/big"
|
|
)
|
|
|
|
// Curve25519 Prime: 2^255 - 19
|
|
var P *big.Int
|
|
|
|
func init() {
|
|
P, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", 16)
|
|
}
|
|
|
|
// Ed25519 Y (Compressed) to Curve25519 (Montgomery) U
|
|
// u = (1 + y) / (1 - y)
|
|
func EdwardsToMontgomery(yBytes []byte) ([]byte, error) {
|
|
// 1. Decode y (little endian, clamped?)
|
|
// "The 32-byte public key is the 32-byte little-endian encoding of the Point."
|
|
// High bit is sign of x (ignored for U-coord conv usually?).
|
|
|
|
// Reverse bytes to big.Int
|
|
y := new(big.Int).SetBytes(Reverse(yBytes))
|
|
|
|
// Clear high bit?
|
|
// Ed25519 compressed form: high bit of last byte is X sign.
|
|
// y &= ~(1 << 255)
|
|
bit255 := big.NewInt(1)
|
|
bit255.Lsh(bit255, 255)
|
|
if y.Cmp(bit255) >= 0 {
|
|
y.Sub(y, bit255)
|
|
}
|
|
|
|
one := big.NewInt(1)
|
|
|
|
// num = 1 + y
|
|
num := new(big.Int).Add(one, y)
|
|
num.Mod(num, P)
|
|
|
|
// den = 1 - y
|
|
den := new(big.Int).Sub(one, y)
|
|
// Handle negative result for modular arithmetic
|
|
if den.Sign() < 0 {
|
|
den.Add(den, P)
|
|
}
|
|
den.Mod(den, P)
|
|
|
|
// denInv
|
|
denInv := new(big.Int).ModInverse(den, P)
|
|
|
|
// u = num * denInv
|
|
u := new(big.Int).Mul(num, denInv)
|
|
u.Mod(u, P)
|
|
|
|
// Encode u (32 bytes little endian)
|
|
uBytes := u.Bytes()
|
|
uBytesRev := Reverse(uBytes)
|
|
|
|
// Pad to 32
|
|
res := make([]byte, 32)
|
|
copy(res, uBytesRev) // Copy into start (little endian usually means LSB at 0?)
|
|
// Wait. BigInt Bytes() returns Big Endian.
|
|
// Reverse(BigEndian) -> Little Endian.
|
|
// If uBytes is shorter than 32, we need to pad ZEROS at the END (high bytes) in Little Endian.
|
|
// e.g. Value 1. BigEndian: [1]. Reverse: [1].
|
|
// Result [1, 0, 0, ...]
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func Reverse(b []byte) []byte {
|
|
l := len(b)
|
|
r := make([]byte, l)
|
|
for i := 0; i < l; i++ {
|
|
r[i] = b[l-1-i]
|
|
}
|
|
return r
|
|
}
|
|
|
|
// CalculateSharedSecret inputs:
|
|
// serverPubKey (Montgomery U, 32 bytes)
|
|
// clientPrivKey (Scalar, 32 bytes)
|
|
func CalculateSharedSecret(serverPub, clientPriv []byte) []byte {
|
|
// Use x/crypto/curve25519
|
|
// ScalarMult(dst, scalar, point)
|
|
// Placeholder as logic is in handshake.go currently
|
|
return nil
|
|
}
|
|
|
|
// Helper to expand hashes
|
|
func Sha1Array(data []byte) [20]byte {
|
|
return sha1.Sum(data)
|
|
}
|
|
func Sha512Array(data []byte) [64]byte {
|
|
return sha512.Sum512(data)
|
|
}
|