1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2023 Sergey Matveev <stargrave@stargrave.org>
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, version 3 of the License.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 zero *big.Int = big.NewInt(0)
25 bigInt1 *big.Int = big.NewInt(1)
26 bigInt2 *big.Int = big.NewInt(2)
27 bigInt3 *big.Int = big.NewInt(3)
28 bigInt4 *big.Int = big.NewInt(4)
32 Name string // Just simple identifier
34 P *big.Int // Characteristic of the underlying prime field
35 Q *big.Int // Elliptic curve subgroup order
37 Co *big.Int // Cofactor
39 // Equation coefficients of the elliptic curve in canonical form
43 // Equation coefficients of the elliptic curve in twisted Edwards form
47 // Basic point X and Y coordinates
51 // Cached s/t parameters for Edwards curve points conversion
56 func NewCurve(p, q, a, b, x, y, e, d, co *big.Int) (*Curve, error) {
66 if !c.Contains(c.X, c.Y) {
67 return nil, errors.New("gogost/gost3410: invalid curve parameters")
69 if e != nil && d != nil {
82 func (c *Curve) Contains(x, y *big.Int) bool {
93 return r1.Cmp(r2) == 0
96 // Get the size of the point's coordinate in bytes.
97 // 32 for 256-bit curves, 64 for 512-bit ones.
98 func (c *Curve) PointSize() int {
102 func (c *Curve) pos(v *big.Int) {
108 func (c *Curve) add(p1x, p1y, p2x, p2y *big.Int) {
109 var t, tx, ty big.Int
110 if p1x.Cmp(p2x) == 0 && p1y.Cmp(p2y) == 0 {
116 tx.ModInverse(&tx, c.P)
126 t.ModInverse(&tx, c.P)
144 func (c *Curve) Exp(degree, xS, yS *big.Int) (*big.Int, *big.Int, error) {
145 if degree.Cmp(zero) == 0 {
146 return nil, nil, errors.New("gogost/gost3410: zero degree value")
148 dg := big.NewInt(0).Sub(degree, bigInt1)
149 tx := big.NewInt(0).Set(xS)
150 ty := big.NewInt(0).Set(yS)
151 cx := big.NewInt(0).Set(xS)
152 cy := big.NewInt(0).Set(yS)
153 for dg.Cmp(zero) != 0 {
155 c.add(tx, ty, cx, cy)
158 c.add(cx, cy, cx, cy)
163 func (our *Curve) Equal(their *Curve) bool {
164 return our.P.Cmp(their.P) == 0 &&
165 our.Q.Cmp(their.Q) == 0 &&
166 our.A.Cmp(their.A) == 0 &&
167 our.B.Cmp(their.B) == 0 &&
168 our.X.Cmp(their.X) == 0 &&
169 our.Y.Cmp(their.Y) == 0 &&
170 ((our.E == nil && their.E == nil) || our.E.Cmp(their.E) == 0) &&
171 ((our.D == nil && their.D == nil) || our.D.Cmp(their.D) == 0) &&
172 our.Co.Cmp(their.Co) == 0
175 func (c *Curve) String() string {