package p256k1 import ( "testing" ) func TestGroupElementBasics(t *testing.T) { // Test infinity point var inf GroupElementAffine inf.setInfinity() if !inf.isInfinity() { t.Error("Infinity point should be infinity") } // Test generator point gen := GeneratorAffine if gen.isInfinity() { t.Error("Generator should not be infinity") } // Test validity if !gen.isValid() { t.Error("Generator should be valid") } } func TestGroupElementNegation(t *testing.T) { // Test negation of generator gen := GeneratorAffine var negGen GroupElementAffine negGen.negate(&gen) if negGen.isInfinity() { t.Error("Negation of generator should not be infinity") } // Test double negation var doubleNeg GroupElementAffine doubleNeg.negate(&negGen) if !doubleNeg.equal(&gen) { t.Error("Double negation should return original point") } // Test negation of infinity var inf, negInf GroupElementAffine inf.setInfinity() negInf.negate(&inf) if !negInf.isInfinity() { t.Error("Negation of infinity should be infinity") } } func TestGroupElementSetXY(t *testing.T) { // Test setting coordinates var point GroupElementAffine var x, y FieldElement x.setInt(1) y.setInt(1) point.setXY(&x, &y) if point.isInfinity() { t.Error("Point with coordinates should not be infinity") } // Test that coordinates are preserved if !point.x.equal(&x) { t.Error("X coordinate should be preserved") } if !point.y.equal(&y) { t.Error("Y coordinate should be preserved") } } func TestGroupElementSetXOVar(t *testing.T) { // Test setting from X coordinate and oddness var x FieldElement x.setInt(1) // This may not be on the curve, but test the function var point GroupElementAffine // Try both odd and even Y success := point.setXOVar(&x, false) if success && point.isInfinity() { t.Error("Successfully created point should not be infinity") } success = point.setXOVar(&x, true) if success && point.isInfinity() { t.Error("Successfully created point should not be infinity") } } func TestGroupElementEquality(t *testing.T) { // Test equality with same point gen := GeneratorAffine var gen2 GroupElementAffine gen2 = gen if !gen.equal(&gen2) { t.Error("Same points should be equal") } // Test inequality with different points var negGen GroupElementAffine negGen.negate(&gen) if gen.equal(&negGen) { t.Error("Generator and its negation should not be equal") } // Test equality of infinity points var inf1, inf2 GroupElementAffine inf1.setInfinity() inf2.setInfinity() if !inf1.equal(&inf2) { t.Error("Two infinity points should be equal") } // Test inequality between infinity and non-infinity if gen.equal(&inf1) { t.Error("Generator and infinity should not be equal") } } func TestGroupElementJacobianBasics(t *testing.T) { // Test infinity var inf GroupElementJacobian inf.setInfinity() if !inf.isInfinity() { t.Error("Jacobian infinity should be infinity") } // Test conversion from affine gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) if genJ.isInfinity() { t.Error("Jacobian generator should not be infinity") } // Test conversion back to affine var genBack GroupElementAffine genBack.setGEJ(&genJ) if !genBack.equal(&gen) { t.Error("Round-trip conversion should preserve point") } } func TestGroupElementJacobianDoubling(t *testing.T) { // Test point doubling gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) var doubled GroupElementJacobian doubled.double(&genJ) if doubled.isInfinity() { t.Error("Doubled generator should not be infinity") } // Test doubling infinity var inf, doubledInf GroupElementJacobian inf.setInfinity() doubledInf.double(&inf) if !doubledInf.isInfinity() { t.Error("Doubled infinity should be infinity") } // Test that 2*P != P (for non-zero points) var doubledAffine GroupElementAffine doubledAffine.setGEJ(&doubled) if doubledAffine.equal(&gen) { t.Error("2*G should not equal G") } } func TestGroupElementJacobianAddition(t *testing.T) { // Test P + O = P (where O is infinity) gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) var inf GroupElementJacobian inf.setInfinity() var result GroupElementJacobian result.addVar(&genJ, &inf) var resultAffine GroupElementAffine resultAffine.setGEJ(&result) if !resultAffine.equal(&gen) { t.Error("P + O should equal P") } // Test O + P = P result.addVar(&inf, &genJ) resultAffine.setGEJ(&result) if !resultAffine.equal(&gen) { t.Error("O + P should equal P") } // Test P + (-P) = O var negGen GroupElementAffine negGen.negate(&gen) var negGenJ GroupElementJacobian negGenJ.setGE(&negGen) result.addVar(&genJ, &negGenJ) if !result.isInfinity() { t.Error("P + (-P) should equal infinity") } // Test P + P = 2P (should equal doubling) var sum, doubled GroupElementJacobian sum.addVar(&genJ, &genJ) doubled.double(&genJ) var sumAffine, doubledAffine GroupElementAffine sumAffine.setGEJ(&sum) doubledAffine.setGEJ(&doubled) if !sumAffine.equal(&doubledAffine) { t.Error("P + P should equal 2*P") } } func TestGroupElementAddGE(t *testing.T) { // Test mixed addition (Jacobian + Affine) gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) var negGen GroupElementAffine negGen.negate(&gen) var result GroupElementJacobian result.addGE(&genJ, &negGen) if !result.isInfinity() { t.Error("P + (-P) should equal infinity in mixed addition") } // Test adding infinity var inf GroupElementAffine inf.setInfinity() result.addGE(&genJ, &inf) var resultAffine GroupElementAffine resultAffine.setGEJ(&result) if !resultAffine.equal(&gen) { t.Error("P + O should equal P in mixed addition") } } func TestGroupElementNegationJacobian(t *testing.T) { // Test Jacobian negation gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) var negGenJ GroupElementJacobian negGenJ.negate(&genJ) if negGenJ.isInfinity() { t.Error("Negated Jacobian point should not be infinity") } // Convert back to affine and compare var negGenAffine, expectedNegAffine GroupElementAffine negGenAffine.setGEJ(&negGenJ) expectedNegAffine.negate(&gen) if !negGenAffine.equal(&expectedNegAffine) { t.Error("Jacobian negation should match affine negation") } } func TestGroupElementStorage(t *testing.T) { // Test storage conversion gen := GeneratorAffine var storage GroupElementStorage gen.toStorage(&storage) var restored GroupElementAffine restored.fromStorage(&storage) if !restored.equal(&gen) { t.Error("Storage round-trip should preserve point") } } func TestGroupElementBytes(t *testing.T) { // Test byte conversion gen := GeneratorAffine var bytes [64]byte gen.toBytes(bytes[:]) var restored GroupElementAffine restored.fromBytes(bytes[:]) if !restored.equal(&gen) { t.Error("Byte round-trip should preserve point") } } func TestGroupElementClear(t *testing.T) { // Test clearing affine point gen := GeneratorAffine gen.clear() if !gen.isInfinity() { t.Error("Cleared affine point should be infinity") } // Test clearing Jacobian point var genJ GroupElementJacobian genJ.setGE(&GeneratorAffine) genJ.clear() if !genJ.isInfinity() { t.Error("Cleared Jacobian point should be infinity") } } func TestGroupElementRandomOperations(t *testing.T) { // Test with random scalar multiplications (simplified) gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) // Test associativity: (P + P) + P = P + (P + P) var p_plus_p, left, right GroupElementJacobian p_plus_p.addVar(&genJ, &genJ) left.addVar(&p_plus_p, &genJ) right.addVar(&genJ, &p_plus_p) var leftAffine, rightAffine GroupElementAffine leftAffine.setGEJ(&left) rightAffine.setGEJ(&right) if !leftAffine.equal(&rightAffine) { t.Error("Addition should be associative") } // Test commutativity: P + Q = Q + P var doubled GroupElementJacobian doubled.double(&genJ) var sum1, sum2 GroupElementJacobian sum1.addVar(&genJ, &doubled) sum2.addVar(&doubled, &genJ) var sum1Affine, sum2Affine GroupElementAffine sum1Affine.setGEJ(&sum1) sum2Affine.setGEJ(&sum2) if !sum1Affine.equal(&sum2Affine) { t.Error("Addition should be commutative") } } func TestGroupElementEdgeCases(t *testing.T) { // Test operations with infinity var inf GroupElementAffine inf.setInfinity() // Test negation of infinity var negInf GroupElementAffine negInf.negate(&inf) if !negInf.isInfinity() { t.Error("Negation of infinity should be infinity") } // Test setting infinity to coordinates (should remain infinity) var x, y FieldElement x.setInt(0) y.setInt(0) inf.setXY(&x, &y) if inf.isInfinity() { t.Error("Setting coordinates should make point non-infinity") } // Reset to infinity for next test inf.setInfinity() // Test conversion of infinity to Jacobian var infJ GroupElementJacobian infJ.setGE(&inf) if !infJ.isInfinity() { t.Error("Jacobian conversion of infinity should be infinity") } // Test conversion back var infBack GroupElementAffine infBack.setGEJ(&infJ) if !infBack.isInfinity() { t.Error("Affine conversion of Jacobian infinity should be infinity") } } func TestGroupElementMultipleDoubling(t *testing.T) { // Test multiple doublings: 2^n * G gen := GeneratorAffine var current GroupElementJacobian current.setGE(&gen) var powers [8]GroupElementAffine powers[0] = gen // Compute 2^i * G for i = 1..7 for i := 1; i < 8; i++ { current.double(¤t) powers[i].setGEJ(¤t) if powers[i].isInfinity() { t.Errorf("2^%d * G should not be infinity", i) } // Check that each power is different from previous ones for j := 0; j < i; j++ { if powers[i].equal(&powers[j]) { t.Errorf("2^%d * G should not equal 2^%d * G", i, j) } } } } // Benchmark tests func BenchmarkGroupElementDouble(b *testing.B) { gen := GeneratorAffine var genJ, result GroupElementJacobian genJ.setGE(&gen) b.ResetTimer() for i := 0; i < b.N; i++ { result.double(&genJ) } } func BenchmarkGroupElementAddVar(b *testing.B) { gen := GeneratorAffine var genJ, doubled, result GroupElementJacobian genJ.setGE(&gen) doubled.double(&genJ) b.ResetTimer() for i := 0; i < b.N; i++ { result.addVar(&genJ, &doubled) } } func BenchmarkGroupElementAddGE(b *testing.B) { gen := GeneratorAffine var genJ, result GroupElementJacobian genJ.setGE(&gen) var negGen GroupElementAffine negGen.negate(&gen) b.ResetTimer() for i := 0; i < b.N; i++ { result.addGE(&genJ, &negGen) } } func BenchmarkGroupElementSetGEJ(b *testing.B) { gen := GeneratorAffine var genJ GroupElementJacobian genJ.setGE(&gen) var result GroupElementAffine b.ResetTimer() for i := 0; i < b.N; i++ { result.setGEJ(&genJ) } } func BenchmarkGroupElementNegate(b *testing.B) { gen := GeneratorAffine var result GroupElementAffine b.ResetTimer() for i := 0; i < b.N; i++ { result.negate(&gen) } }