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)} }