working
This commit is contained in:
97
pkg/protocol/math.go
Normal file
97
pkg/protocol/math.go
Normal file
@@ -0,0 +1,97 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user