From 81184285edbbf0e1371c87a6f9d506ecc3517f96 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Fri, 11 Jul 2025 11:56:18 +0100 Subject: [PATCH] add back special case handling --- crypto/modexp/gmp/gmp.go | 11 +++++++ crypto/modexp/gmp/gmp_test.go | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/crypto/modexp/gmp/gmp.go b/crypto/modexp/gmp/gmp.go index 70e8e5504d..c40b83e89f 100644 --- a/crypto/modexp/gmp/gmp.go +++ b/crypto/modexp/gmp/gmp.go @@ -45,6 +45,17 @@ func ModExp(base, exp, mod []byte) ([]byte, error) { return []byte{}, nil } + // Special case: base == 1 + // If base is 1, the result is always 1 (when mod > 1) + if len(base) == 1 && base[0] == 1 { + // For modulus > 1, 1^exp mod modulus = 1 + // For modulus == 1, any number mod 1 = 0 + if len(mod) == 1 && mod[0] == 1 { + return []byte{}, nil + } + return []byte{1}, nil + } + // Allocate result buffer (size of modulus is the max possible result) result := make([]byte, len(mod)) resultLen := C.size_t(len(result)) diff --git a/crypto/modexp/gmp/gmp_test.go b/crypto/modexp/gmp/gmp_test.go index 5ac253dfb1..c6e479cf02 100644 --- a/crypto/modexp/gmp/gmp_test.go +++ b/crypto/modexp/gmp/gmp_test.go @@ -133,3 +133,57 @@ func BenchmarkModExpBigInt(b *testing.B) { _ = result.Bytes() } } + +// TestSpecialCases tests the special case optimizations +func TestSpecialCases(t *testing.T) { + tests := []struct { + name string + base []byte + exp []byte + mod []byte + expected []byte + }{ + { + name: "base_one_mod_large", + base: []byte{1}, + exp: []byte{255, 255, 255, 255}, // large exponent + mod: []byte{100}, + expected: []byte{1}, + }, + { + name: "base_one_mod_one", + base: []byte{1}, + exp: []byte{10}, + mod: []byte{1}, + expected: []byte{}, // 1 mod 1 = 0 + }, + { + name: "zero_modulus", + base: []byte{2}, + exp: []byte{3}, + mod: []byte{}, + expected: []byte{}, + }, + { + name: "all_zero_modulus", + base: []byte{2}, + exp: []byte{3}, + mod: []byte{0, 0, 0}, + expected: []byte{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := ModExp(tt.base, tt.exp, tt.mod) + if err != nil { + t.Fatalf("ModExp error: %v", err) + } + + if !bytes.Equal(result, tt.expected) { + t.Errorf("Results differ:\nGot: %x\nExpected: %x", + result, tt.expected) + } + }) + } +}