aboutsummaryrefslogtreecommitdiffstats
path: root/field.go
diff options
context:
space:
mode:
authorClawd <ai@clawd.bot>2026-02-19 20:21:41 -0800
committerClawd <ai@clawd.bot>2026-02-19 20:21:41 -0800
commite0f87d3752edd792b7993d64622c216ebda225f4 (patch)
treed11888bb28e70f4abce7502dd307dba5d2a31631 /field.go
parent90e12ea00741861bdf53ffb5826cb4a97ae0106a (diff)
Add field arithmetic (mod p operations)
Diffstat (limited to 'field.go')
-rw-r--r--field.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/field.go b/field.go
new file mode 100644
index 0000000..8b865ad
--- /dev/null
+++ b/field.go
@@ -0,0 +1,92 @@
1package main
2
3import (
4 "fmt"
5 "math/big"
6)
7
8// The prime for secp256k1: 2^256 - 2^32 - 977
9// All field arithmetic happens mod this number
10var P, _ = new(big.Int).SetString(
11 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
12 16,
13)
14
15// FieldElement represents a number in our finite field (mod P)
16type FieldElement struct {
17 value *big.Int
18}
19
20// NewFieldElement creates a field element from a big.Int
21// It automatically reduces mod P
22func NewFieldElement(v *big.Int) *FieldElement {
23 result := new(big.Int).Mod(v, P)
24 return &FieldElement{value: result}
25}
26
27// NewFieldElementFromInt64 is a convenience for small numbers
28func NewFieldElementFromInt64(v int64) *FieldElement {
29 return NewFieldElement(big.NewInt(v))
30}
31
32// Add returns (a + b) mod P
33func (a *FieldElement) Add(b *FieldElement) *FieldElement {
34 result := new(big.Int).Add(a.value, b.value)
35 return NewFieldElement(result)
36}
37
38// Sub returns (a - b) mod P
39func (a *FieldElement) Sub(b *FieldElement) *FieldElement {
40 result := new(big.Int).Sub(a.value, b.value)
41 return NewFieldElement(result)
42}
43
44// Mul returns (a * b) mod P
45func (a *FieldElement) Mul(b *FieldElement) *FieldElement {
46 result := new(big.Int).Mul(a.value, b.value)
47 return NewFieldElement(result)
48}
49
50// Div returns (a / b) mod P
51// Division in a field = multiply by the inverse
52func (a *FieldElement) Div(b *FieldElement) *FieldElement {
53 // a / b = a * b^(-1)
54 // b^(-1) mod P = b^(P-2) mod P (Fermat's little theorem)
55 inverse := b.Inverse()
56 return a.Mul(inverse)
57}
58
59// Inverse returns a^(-1) mod P using Fermat's little theorem
60// a^(-1) = a^(P-2) mod P
61func (a *FieldElement) Inverse() *FieldElement {
62 // P - 2
63 exp := new(big.Int).Sub(P, big.NewInt(2))
64 // a^(P-2) mod P
65 result := new(big.Int).Exp(a.value, exp, P)
66 return &FieldElement{value: result}
67}
68
69// Square returns a² mod P (convenience method)
70func (a *FieldElement) Square() *FieldElement {
71 return a.Mul(a)
72}
73
74// Equal checks if two field elements are the same
75func (a *FieldElement) Equal(b *FieldElement) bool {
76 return a.value.Cmp(b.value) == 0
77}
78
79// IsZero checks if the element is zero
80func (a *FieldElement) IsZero() bool {
81 return a.value.Sign() == 0
82}
83
84// String returns hex representation
85func (a *FieldElement) String() string {
86 return fmt.Sprintf("%064x", a.value)
87}
88
89// Clone returns a copy
90func (a *FieldElement) Clone() *FieldElement {
91 return &FieldElement{value: new(big.Int).Set(a.value)}
92}