This commit is contained in:
Jose Luis Montañes Ojados
2026-01-15 16:49:16 +01:00
commit 47b8173045
23 changed files with 2864 additions and 0 deletions

97
pkg/protocol/math.go Normal file
View 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)
}