Skip to content

Commit cf50ffe

Browse files
committed
Add GOST cryptography implementation including elliptic curves, digital signatures, HMAC, and TLS support
1 parent b625199 commit cf50ffe

11 files changed

Lines changed: 2414 additions & 0 deletions

File tree

crypto/ru/gost/curves.go

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
// GOST R 34.10-2012 elliptic curves.
2+
// Defines curve parameters for 256-bit and 512-bit key sizes.
3+
package gost
4+
5+
import (
6+
"crypto/elliptic"
7+
"math/big"
8+
"sync"
9+
)
10+
11+
// Curve represents a GOST elliptic curve.
12+
type Curve struct {
13+
elliptic.CurveParams
14+
A *big.Int // Curve coefficient a (standard elliptic has a=-3, GOST uses custom)
15+
}
16+
17+
// Params returns the curve parameters.
18+
func (c *Curve) Params() *elliptic.CurveParams {
19+
return &c.CurveParams
20+
}
21+
22+
// IsOnCurve reports whether the point (x,y) is on the curve.
23+
func (c *Curve) IsOnCurve(x, y *big.Int) bool {
24+
// y² = x³ + ax + b (mod p)
25+
y2 := new(big.Int).Mul(y, y)
26+
y2.Mod(y2, c.P)
27+
28+
x3 := new(big.Int).Mul(x, x)
29+
x3.Mul(x3, x)
30+
31+
ax := new(big.Int).Mul(c.A, x)
32+
33+
rhs := new(big.Int).Add(x3, ax)
34+
rhs.Add(rhs, c.B)
35+
rhs.Mod(rhs, c.P)
36+
37+
return y2.Cmp(rhs) == 0
38+
}
39+
40+
// Add returns the sum of (x1,y1) and (x2,y2).
41+
func (c *Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
42+
// Handle identity
43+
if x1.Sign() == 0 && y1.Sign() == 0 {
44+
return new(big.Int).Set(x2), new(big.Int).Set(y2)
45+
}
46+
if x2.Sign() == 0 && y2.Sign() == 0 {
47+
return new(big.Int).Set(x1), new(big.Int).Set(y1)
48+
}
49+
50+
// Check if points are the same
51+
if x1.Cmp(x2) == 0 {
52+
if y1.Cmp(y2) == 0 {
53+
return c.Double(x1, y1)
54+
}
55+
// Points are inverse, return identity
56+
return new(big.Int), new(big.Int)
57+
}
58+
59+
// λ = (y2 - y1) / (x2 - x1)
60+
dy := new(big.Int).Sub(y2, y1)
61+
dx := new(big.Int).Sub(x2, x1)
62+
dx.ModInverse(dx, c.P)
63+
lambda := new(big.Int).Mul(dy, dx)
64+
lambda.Mod(lambda, c.P)
65+
66+
// x3 = λ² - x1 - x2
67+
x3 := new(big.Int).Mul(lambda, lambda)
68+
x3.Sub(x3, x1)
69+
x3.Sub(x3, x2)
70+
x3.Mod(x3, c.P)
71+
72+
// y3 = λ(x1 - x3) - y1
73+
y3 := new(big.Int).Sub(x1, x3)
74+
y3.Mul(y3, lambda)
75+
y3.Sub(y3, y1)
76+
y3.Mod(y3, c.P)
77+
78+
return x3, y3
79+
}
80+
81+
// Double returns 2*(x,y).
82+
func (c *Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
83+
if y1.Sign() == 0 {
84+
return new(big.Int), new(big.Int)
85+
}
86+
87+
// λ = (3x² + a) / 2y
88+
x2 := new(big.Int).Mul(x1, x1)
89+
x2.Mul(x2, big.NewInt(3))
90+
x2.Add(x2, c.A)
91+
92+
y2 := new(big.Int).Mul(y1, big.NewInt(2))
93+
y2.ModInverse(y2, c.P)
94+
95+
lambda := new(big.Int).Mul(x2, y2)
96+
lambda.Mod(lambda, c.P)
97+
98+
// x3 = λ² - 2x1
99+
x3 := new(big.Int).Mul(lambda, lambda)
100+
x3.Sub(x3, x1)
101+
x3.Sub(x3, x1)
102+
x3.Mod(x3, c.P)
103+
104+
// y3 = λ(x1 - x3) - y1
105+
y3 := new(big.Int).Sub(x1, x3)
106+
y3.Mul(y3, lambda)
107+
y3.Sub(y3, y1)
108+
y3.Mod(y3, c.P)
109+
110+
return x3, y3
111+
}
112+
113+
// ScalarMult returns k*(x,y).
114+
func (c *Curve) ScalarMult(x1, y1 *big.Int, k []byte) (*big.Int, *big.Int) {
115+
// Double-and-add
116+
Bx, By := new(big.Int).Set(x1), new(big.Int).Set(y1)
117+
Rx, Ry := new(big.Int), new(big.Int)
118+
119+
for _, b := range k {
120+
for i := 7; i >= 0; i-- {
121+
Rx, Ry = c.Double(Rx, Ry)
122+
if (b>>i)&1 == 1 {
123+
Rx, Ry = c.Add(Rx, Ry, Bx, By)
124+
}
125+
}
126+
}
127+
return Rx, Ry
128+
}
129+
130+
// ScalarBaseMult returns k*G where G is the base point.
131+
func (c *Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
132+
return c.ScalarMult(c.Gx, c.Gy, k)
133+
}
134+
135+
// Curve instances
136+
var (
137+
initOnce sync.Once
138+
139+
// 256-bit curves
140+
CurveIdtc26gost34102012256paramSetA *Curve
141+
142+
// 512-bit curves
143+
CurveIdtc26gost34102012512paramSetA *Curve
144+
CurveIdtc26gost34102012512paramSetB *Curve
145+
CurveIdtc26gost34102012512paramSetC *Curve
146+
)
147+
148+
func initCurves() {
149+
initOnce.Do(func() {
150+
initCurve256A()
151+
initCurve512A()
152+
initCurve512B()
153+
initCurve512C()
154+
})
155+
}
156+
157+
// TC26256A returns the tc26-gost-3410-2012-256-paramSetA curve.
158+
func TC26256A() *Curve {
159+
initCurves()
160+
return CurveIdtc26gost34102012256paramSetA
161+
}
162+
163+
// TC26512A returns the tc26-gost-3410-2012-512-paramSetA curve.
164+
func TC26512A() *Curve {
165+
initCurves()
166+
return CurveIdtc26gost34102012512paramSetA
167+
}
168+
169+
// TC26512B returns the tc26-gost-3410-2012-512-paramSetB curve.
170+
func TC26512B() *Curve {
171+
initCurves()
172+
return CurveIdtc26gost34102012512paramSetB
173+
}
174+
175+
// TC26512C returns the tc26-gost-3410-2012-512-paramSetC curve.
176+
func TC26512C() *Curve {
177+
initCurves()
178+
return CurveIdtc26gost34102012512paramSetC
179+
}
180+
181+
func initCurve256A() {
182+
// id-tc26-gost-3410-2012-256-paramSetA
183+
CurveIdtc26gost34102012256paramSetA = &Curve{}
184+
CurveIdtc26gost34102012256paramSetA.P, _ = new(big.Int).SetString(
185+
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16)
186+
CurveIdtc26gost34102012256paramSetA.N, _ = new(big.Int).SetString(
187+
"400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67", 16)
188+
CurveIdtc26gost34102012256paramSetA.A, _ = new(big.Int).SetString(
189+
"C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335", 16)
190+
CurveIdtc26gost34102012256paramSetA.B, _ = new(big.Int).SetString(
191+
"295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513", 16)
192+
CurveIdtc26gost34102012256paramSetA.Gx, _ = new(big.Int).SetString(
193+
"91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28", 16)
194+
CurveIdtc26gost34102012256paramSetA.Gy, _ = new(big.Int).SetString(
195+
"32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C", 16)
196+
CurveIdtc26gost34102012256paramSetA.BitSize = 256
197+
CurveIdtc26gost34102012256paramSetA.Name = "id-tc26-gost-3410-2012-256-paramSetA"
198+
}
199+
200+
func initCurve512A() {
201+
// id-tc26-gost-3410-2012-512-paramSetA
202+
CurveIdtc26gost34102012512paramSetA = &Curve{}
203+
CurveIdtc26gost34102012512paramSetA.P, _ = new(big.Int).SetString(
204+
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", 16)
205+
CurveIdtc26gost34102012512paramSetA.N, _ = new(big.Int).SetString(
206+
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275", 16)
207+
CurveIdtc26gost34102012512paramSetA.A, _ = new(big.Int).SetString(
208+
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4", 16)
209+
CurveIdtc26gost34102012512paramSetA.B, _ = new(big.Int).SetString(
210+
"E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760", 16)
211+
CurveIdtc26gost34102012512paramSetA.Gx, _ = new(big.Int).SetString(
212+
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", 16)
213+
CurveIdtc26gost34102012512paramSetA.Gy, _ = new(big.Int).SetString(
214+
"7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4", 16)
215+
CurveIdtc26gost34102012512paramSetA.BitSize = 512
216+
CurveIdtc26gost34102012512paramSetA.Name = "id-tc26-gost-3410-2012-512-paramSetA"
217+
}
218+
219+
func initCurve512B() {
220+
// id-tc26-gost-3410-2012-512-paramSetB
221+
CurveIdtc26gost34102012512paramSetB = &Curve{}
222+
CurveIdtc26gost34102012512paramSetB.P, _ = new(big.Int).SetString(
223+
"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F", 16)
224+
CurveIdtc26gost34102012512paramSetB.N, _ = new(big.Int).SetString(
225+
"800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD", 16)
226+
CurveIdtc26gost34102012512paramSetB.A, _ = new(big.Int).SetString(
227+
"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C", 16)
228+
CurveIdtc26gost34102012512paramSetB.B, _ = new(big.Int).SetString(
229+
"687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116", 16)
230+
CurveIdtc26gost34102012512paramSetB.Gx, _ = new(big.Int).SetString(
231+
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002", 16)
232+
CurveIdtc26gost34102012512paramSetB.Gy, _ = new(big.Int).SetString(
233+
"1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD", 16)
234+
CurveIdtc26gost34102012512paramSetB.BitSize = 512
235+
CurveIdtc26gost34102012512paramSetB.Name = "id-tc26-gost-3410-2012-512-paramSetB"
236+
}
237+
238+
func initCurve512C() {
239+
// id-tc26-gost-3410-2012-512-paramSetC (same as paramSetA with different cofactor)
240+
CurveIdtc26gost34102012512paramSetC = &Curve{}
241+
CurveIdtc26gost34102012512paramSetC.P, _ = new(big.Int).SetString(
242+
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", 16)
243+
CurveIdtc26gost34102012512paramSetC.N, _ = new(big.Int).SetString(
244+
"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED", 16)
245+
CurveIdtc26gost34102012512paramSetC.A, _ = new(big.Int).SetString(
246+
"DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3", 16)
247+
CurveIdtc26gost34102012512paramSetC.B, _ = new(big.Int).SetString(
248+
"B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1", 16)
249+
CurveIdtc26gost34102012512paramSetC.Gx, _ = new(big.Int).SetString(
250+
"E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148", 16)
251+
CurveIdtc26gost34102012512paramSetC.Gy, _ = new(big.Int).SetString(
252+
"F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F", 16)
253+
CurveIdtc26gost34102012512paramSetC.BitSize = 512
254+
CurveIdtc26gost34102012512paramSetC.Name = "id-tc26-gost-3410-2012-512-paramSetC"
255+
}

0 commit comments

Comments
 (0)