From e0f87d3752edd792b7993d64622c216ebda225f4 Mon Sep 17 00:00:00 2001 From: Clawd Date: Thu, 19 Feb 2026 20:21:41 -0800 Subject: Add field arithmetic (mod p operations) --- field.go | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 field.go (limited to 'field.go') diff --git a/field.go b/field.go new file mode 100644 index 0000000..8b865ad --- /dev/null +++ b/field.go @@ -0,0 +1,92 @@ +package main + +import ( + "fmt" + "math/big" +) + +// The prime for secp256k1: 2^256 - 2^32 - 977 +// All field arithmetic happens mod this number +var P, _ = new(big.Int).SetString( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + 16, +) + +// FieldElement represents a number in our finite field (mod P) +type FieldElement struct { + value *big.Int +} + +// NewFieldElement creates a field element from a big.Int +// It automatically reduces mod P +func NewFieldElement(v *big.Int) *FieldElement { + result := new(big.Int).Mod(v, P) + return &FieldElement{value: result} +} + +// NewFieldElementFromInt64 is a convenience for small numbers +func NewFieldElementFromInt64(v int64) *FieldElement { + return NewFieldElement(big.NewInt(v)) +} + +// Add returns (a + b) mod P +func (a *FieldElement) Add(b *FieldElement) *FieldElement { + result := new(big.Int).Add(a.value, b.value) + return NewFieldElement(result) +} + +// Sub returns (a - b) mod P +func (a *FieldElement) Sub(b *FieldElement) *FieldElement { + result := new(big.Int).Sub(a.value, b.value) + return NewFieldElement(result) +} + +// Mul returns (a * b) mod P +func (a *FieldElement) Mul(b *FieldElement) *FieldElement { + result := new(big.Int).Mul(a.value, b.value) + return NewFieldElement(result) +} + +// Div returns (a / b) mod P +// Division in a field = multiply by the inverse +func (a *FieldElement) Div(b *FieldElement) *FieldElement { + // a / b = a * b^(-1) + // b^(-1) mod P = b^(P-2) mod P (Fermat's little theorem) + inverse := b.Inverse() + return a.Mul(inverse) +} + +// Inverse returns a^(-1) mod P using Fermat's little theorem +// a^(-1) = a^(P-2) mod P +func (a *FieldElement) Inverse() *FieldElement { + // P - 2 + exp := new(big.Int).Sub(P, big.NewInt(2)) + // a^(P-2) mod P + result := new(big.Int).Exp(a.value, exp, P) + return &FieldElement{value: result} +} + +// Square returns a² mod P (convenience method) +func (a *FieldElement) Square() *FieldElement { + return a.Mul(a) +} + +// Equal checks if two field elements are the same +func (a *FieldElement) Equal(b *FieldElement) bool { + return a.value.Cmp(b.value) == 0 +} + +// IsZero checks if the element is zero +func (a *FieldElement) IsZero() bool { + return a.value.Sign() == 0 +} + +// String returns hex representation +func (a *FieldElement) String() string { + return fmt.Sprintf("%064x", a.value) +} + +// Clone returns a copy +func (a *FieldElement) Clone() *FieldElement { + return &FieldElement{value: new(big.Int).Set(a.value)} +} -- cgit v1.2.3