Files
go-ts/pkg/protocol/crypto_init2_test.go

102 lines
2.8 KiB
Go
Raw Permalink Normal View History

2026-01-15 16:49:16 +01:00
package protocol
import (
"crypto/sha1"
"crypto/sha512"
"encoding/hex"
"strings"
"testing"
"filippo.io/edwards25519"
)
// Helper to match ts3j hex string decoding
func hexBytes(s string) []byte {
b, _ := hex.DecodeString(s)
return b
}
func TestCryptoInit2_Ts3jVectors(t *testing.T) {
// Vectors from ts3j CryptoInit2Test.java
licenseBytes := hexBytes("0100358541498A24ACD30157918B8F50955C0DAE970AB65372CBE407" +
"415FCF3E029B02084D15E00AA793600700000020416E6F6E796D6F7573000047D9E4DC25AA2E90ACD4DB5FA61C8F" +
"ED369B346D84C2CA2FCCCA86F73AFEF092200A77C8810A787141")
alpha := hexBytes("9500A5DB3B50ACECAB81")
beta := hexBytes("EAFFC9A8BC996B25C8AA700264E99E372ECCDEB1C121D6EC0F4D49FB46" +
"CEEBA4E3C724B3070FD70CB03D7BC08129205690ECE228CA7C")
privateKeyBytes := hexBytes("102E591ABA4508129E812FF3437E2DDD3CA1F1EC341117CA35" +
"14CC347A7C2A77")
expectedIvStructHex := "E4082A92F71C96A947452F5582EF2879B2051ED2D3" +
"F2C6B0643CF5A266EE6B5180573C2F5F3F1C4AC579188366F16AE0EADC3AAF860805D8F2A831E9E49F4513"
expectedFakeSigHex := "54F2B4D661E0F9AB"
// 1. Derive Server Public Key (License)
serverPubBytes, err := ParseLicenseAndDeriveKey(licenseBytes)
if err != nil {
t.Fatalf("ParseLicenseAndDeriveKey failed: %v", err)
}
// 2. Derive Shared Secret (simulating ts3j generateSharedSecret2)
// Load Server Point
serverPoint, err := new(edwards25519.Point).SetBytes(serverPubBytes)
if err != nil {
t.Fatalf("Invalid server pub key derived: %v", err)
}
// Negate Server Point
serverPoint.Negate(serverPoint)
// Create Scalar from private key
scalarBytes := make([]byte, 32)
copy(scalarBytes, privateKeyBytes)
scalarBytes[31] &= 0x7F // ts3j specific masking
// Load Scalar
scalar, err := new(edwards25519.Scalar).SetBytesWithClamping(scalarBytes)
if err != nil {
t.Fatalf("Scalar load failed: %v", err)
}
// Multiply
sharedPoint := new(edwards25519.Point).ScalarMult(scalar, serverPoint)
sharedBytes := sharedPoint.Bytes()
// Flip Sign
sharedBytes[31] ^= 0x80
// Hash
sharedSecret := sha512.Sum512(sharedBytes)
// 3. Calculate IV/Mac
// IV = XOR(SharedSecret, Alpha) ++ XOR(SharedSecret, Beta)
ivStruct := make([]byte, 64)
copy(ivStruct, sharedSecret[:])
for i := 0; i < 10; i++ {
ivStruct[i] ^= alpha[i]
}
if len(beta) < 54 {
t.Fatal("Beta too short")
}
for i := 0; i < 54; i++ {
ivStruct[10+i] ^= beta[i]
}
// FakeSig = SHA1(IV)[0..8]
macHash := sha1.Sum(ivStruct)
fakeSig := macHash[0:8]
// Compare
gotIvHex := hex.EncodeToString(ivStruct)
if !strings.EqualFold(gotIvHex, expectedIvStructHex) {
t.Errorf("IV Struct Mismatch.\nGot: %s\nWant: %s", gotIvHex, expectedIvStructHex)
}
gotSigHex := hex.EncodeToString(fakeSig)
if !strings.EqualFold(gotSigHex, expectedFakeSigHex) {
t.Errorf("FakeSig Mismatch.\nGot: %s\nWant: %s", gotSigHex, expectedFakeSigHex)
}
}