blob: 13cdffd425896543151bb40725d74a07102b9fbe (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
package secp256k1
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)}
}
|