]> Cypherpunks.ru repositories - gogost.git/blob - src/cypherpunks.ru/gogost/gost3410/curve.go
1.1 release is ready
[gogost.git] / src / cypherpunks.ru / gogost / gost3410 / curve.go
1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 package gost3410
18
19 import (
20         "errors"
21         "math/big"
22 )
23
24 var (
25         zero    *big.Int = big.NewInt(0)
26         bigInt1 *big.Int = big.NewInt(1)
27         bigInt2 *big.Int = big.NewInt(2)
28         bigInt3 *big.Int = big.NewInt(3)
29 )
30
31 type Curve struct {
32         P *big.Int
33         Q *big.Int
34         A *big.Int
35         B *big.Int
36
37         // Basic point X and Y coordinates
38         Bx *big.Int
39         By *big.Int
40
41         // Temporary variable for the add method
42         t  *big.Int
43         tx *big.Int
44         ty *big.Int
45 }
46
47 func NewCurve(p, q, a, b, bx, by []byte) (*Curve, error) {
48         c := Curve{
49                 P:  bytes2big(p[:]),
50                 Q:  bytes2big(q[:]),
51                 A:  bytes2big(a[:]),
52                 B:  bytes2big(b[:]),
53                 Bx: bytes2big(bx[:]),
54                 By: bytes2big(by[:]),
55                 t:  big.NewInt(0),
56                 tx: big.NewInt(0),
57                 ty: big.NewInt(0),
58         }
59         r1 := big.NewInt(0)
60         r2 := big.NewInt(0)
61         r1.Mul(c.By, c.By)
62         r1.Mod(r1, c.P)
63         r2.Mul(c.Bx, c.Bx)
64         r2.Add(r2, c.A)
65         r2.Mul(r2, c.Bx)
66         r2.Add(r2, c.B)
67         r2.Mod(r2, c.P)
68         if r2.Cmp(big.NewInt(0)) == -1 {
69                 r2.Add(r2, c.P)
70         }
71         if r1.Cmp(r2) != 0 {
72                 return nil, errors.New("Invalid curve parameters")
73         }
74         return &c, nil
75 }
76
77 func (c *Curve) pos(v *big.Int) {
78         if v.Cmp(zero) < 0 {
79                 v.Add(v, c.P)
80         }
81 }
82
83 func (c *Curve) add(p1x, p1y, p2x, p2y *big.Int) {
84         if p1x.Cmp(p2x) == 0 && p1y.Cmp(p2y) == 0 {
85                 // double
86                 c.t.Mul(p1x, p1x)
87                 c.t.Mul(c.t, bigInt3)
88                 c.t.Add(c.t, c.A)
89                 c.tx.Mul(bigInt2, p1y)
90                 c.tx.ModInverse(c.tx, c.P)
91                 c.t.Mul(c.t, c.tx)
92                 c.t.Mod(c.t, c.P)
93         } else {
94                 c.tx.Sub(p2x, p1x)
95                 c.tx.Mod(c.tx, c.P)
96                 c.pos(c.tx)
97                 c.ty.Sub(p2y, p1y)
98                 c.ty.Mod(c.ty, c.P)
99                 c.pos(c.ty)
100                 c.t.ModInverse(c.tx, c.P)
101                 c.t.Mul(c.t, c.ty)
102                 c.t.Mod(c.t, c.P)
103         }
104         c.tx.Mul(c.t, c.t)
105         c.tx.Sub(c.tx, p1x)
106         c.tx.Sub(c.tx, p2x)
107         c.tx.Mod(c.tx, c.P)
108         c.pos(c.tx)
109         c.ty.Sub(p1x, c.tx)
110         c.ty.Mul(c.ty, c.t)
111         c.ty.Sub(c.ty, p1y)
112         c.ty.Mod(c.ty, c.P)
113         c.pos(c.ty)
114         p1x.Set(c.tx)
115         p1y.Set(c.ty)
116 }
117
118 func (c *Curve) Exp(degree, xS, yS *big.Int) (*big.Int, *big.Int, error) {
119         dg := big.NewInt(0).Sub(degree, bigInt1)
120         tx := big.NewInt(0).Set(xS)
121         ty := big.NewInt(0).Set(yS)
122         cx := big.NewInt(0).Set(xS)
123         cy := big.NewInt(0).Set(yS)
124         if dg.Cmp(zero) == 0 {
125                 return nil, nil, errors.New("Bad degree value")
126         }
127         for dg.Cmp(zero) != 0 {
128                 if dg.Bit(0) == 1 {
129                         c.add(tx, ty, cx, cy)
130                 }
131                 dg.Rsh(dg, 1)
132                 c.add(cx, cy, cx, cy)
133         }
134         return tx, ty, nil
135 }