starkbank-ecdsa 0.0.5 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/curve.rb +112 -0
- data/lib/ecdsa.rb +48 -18
- data/lib/math.rb +499 -0
- data/lib/point.rb +19 -0
- data/lib/privatekey.rb +45 -30
- data/lib/publickey.rb +85 -14
- data/lib/signature.rb +37 -21
- data/lib/starkbank-ecdsa.rb +9 -1
- data/lib/utils/binary.rb +51 -0
- data/lib/utils/der.rb +184 -0
- data/lib/utils/file.rb +0 -6
- data/lib/utils/integer.rb +89 -0
- data/lib/utils/oid.rb +43 -0
- data/lib/utils/pem.rb +18 -0
- metadata +11 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b661f1bd378387d7c6466e9271adba268c3e85e7cc3a65ed71bb4e26a6e26d5
|
|
4
|
+
data.tar.gz: 9f815e7c6c4a95f302b12a0458eb6ab24596ff0df5a8cfcb51a608f463ee1b42
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 62071d28e66c906ee70a2a3fe8bc5de2c4174cee49e0d90eb1f19b76014573462ad14035941717f162486dc33780b14e8fbddefff415249d70ba8a16fe79e75a
|
|
7
|
+
data.tar.gz: c1c599e3c8d5bb1f998fe91fdebf54f8b5efd43fb9644fac8425e5f9a20f3dab29b5a430763777b40800e27c7eba106d20c47195caa0ba27520bb5549a2ea3ea
|
data/lib/curve.rb
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module EllipticCurve
|
|
2
|
+
#
|
|
3
|
+
# Elliptic Curve Equation
|
|
4
|
+
#
|
|
5
|
+
# y^2 = x^3 + A*x + B (mod P)
|
|
6
|
+
#
|
|
7
|
+
module Curve
|
|
8
|
+
class CurveFp
|
|
9
|
+
attr_accessor :a, :b, :p, :n, :g, :name, :oid, :nistName, :nBitLength, :glvParams
|
|
10
|
+
attr_accessor :_generatorPowersTable
|
|
11
|
+
|
|
12
|
+
def initialize(a, b, p, n, gx, gy, name, oid, nistName=nil, glvParams=nil)
|
|
13
|
+
@a = a
|
|
14
|
+
@b = b
|
|
15
|
+
@p = p
|
|
16
|
+
@n = n
|
|
17
|
+
@nBitLength = n.bit_length
|
|
18
|
+
@g = Point.new(gx, gy)
|
|
19
|
+
@name = name
|
|
20
|
+
@oid = oid
|
|
21
|
+
@nistName = nistName
|
|
22
|
+
# GLV endomorphism parameters (only for curves that support one,
|
|
23
|
+
# e.g. secp256k1). nil means no endomorphism; fall back to Shamir+JSF.
|
|
24
|
+
@glvParams = glvParams
|
|
25
|
+
@_generatorPowersTable = nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def contains(p)
|
|
29
|
+
# Verify if the point `p` is on the curve
|
|
30
|
+
# :param p: point p = Point(x, y)
|
|
31
|
+
# :return: boolean
|
|
32
|
+
if not (0 <= p.x and p.x <= @p - 1)
|
|
33
|
+
return false
|
|
34
|
+
end
|
|
35
|
+
if not (0 <= p.y and p.y <= @p - 1)
|
|
36
|
+
return false
|
|
37
|
+
end
|
|
38
|
+
if (p.y ** 2 - (p.x ** 3 + @a * p.x + @b)) % @p != 0
|
|
39
|
+
return false
|
|
40
|
+
end
|
|
41
|
+
return true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def length
|
|
45
|
+
return (1 + ("%x" % @n).length).div(2)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def y(x, isEven)
|
|
49
|
+
ySquared = (x.pow(3, @p) + @a * x + @b) % @p
|
|
50
|
+
y = Math::modularSquareRoot(ySquared, @p)
|
|
51
|
+
if isEven != (y % 2 == 0)
|
|
52
|
+
y = @p - y
|
|
53
|
+
end
|
|
54
|
+
return y
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@_curvesByOid = { }
|
|
60
|
+
|
|
61
|
+
def self.add(curve)
|
|
62
|
+
@_curvesByOid[curve.oid] = curve
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.getbyOid(oid)
|
|
66
|
+
if not @_curvesByOid.include?(oid)
|
|
67
|
+
raise Exception.new("Unknown curve oid: #{oid}; The following are registered: #{@_curvesByOid.map{|k,v| v.name}}")
|
|
68
|
+
end
|
|
69
|
+
return @_curvesByOid[oid]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
SECP256K1 = CurveFp.new(
|
|
73
|
+
0x0000000000000000000000000000000000000000000000000000000000000000,
|
|
74
|
+
0x0000000000000000000000000000000000000000000000000000000000000007,
|
|
75
|
+
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
|
76
|
+
0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
|
|
77
|
+
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
|
|
78
|
+
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
|
|
79
|
+
"secp256k1",
|
|
80
|
+
[1, 3, 132, 0, 10],
|
|
81
|
+
nil,
|
|
82
|
+
# GLV endomorphism phi((x,y)) = (beta*x, y), equivalent to lambda*P.
|
|
83
|
+
# Basis vectors from Gauss reduction; used to split a 256-bit scalar k
|
|
84
|
+
# into two ~128-bit scalars (k1, k2) with k == k1 + k2*lambda (mod N).
|
|
85
|
+
{
|
|
86
|
+
:beta => 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee,
|
|
87
|
+
:lambda => 0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72,
|
|
88
|
+
:a1 => 0x3086d221a7d46bcde86c90e49284eb15,
|
|
89
|
+
:b1 => -0xe4437ed6010e88286f547fa90abfe4c3,
|
|
90
|
+
:a2 => 0x114ca50f7a8e2f3f657c1108d9d44cfd8,
|
|
91
|
+
:b2 => 0x3086d221a7d46bcde86c90e49284eb15,
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
PRIME256V1 = CurveFp.new(
|
|
96
|
+
0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc,
|
|
97
|
+
0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b,
|
|
98
|
+
0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff,
|
|
99
|
+
0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551,
|
|
100
|
+
0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,
|
|
101
|
+
0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5,
|
|
102
|
+
"prime256v1",
|
|
103
|
+
[1, 2, 840, 10045, 3, 1, 7],
|
|
104
|
+
"p-256",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
P256 = PRIME256V1
|
|
108
|
+
|
|
109
|
+
self.add(PRIME256V1)
|
|
110
|
+
self.add(SECP256K1)
|
|
111
|
+
end
|
|
112
|
+
end
|
data/lib/ecdsa.rb
CHANGED
|
@@ -1,32 +1,62 @@
|
|
|
1
1
|
require 'digest'
|
|
2
|
-
require 'openssl'
|
|
3
|
-
require_relative './signature'
|
|
4
2
|
|
|
5
3
|
|
|
6
4
|
module EllipticCurve
|
|
7
|
-
|
|
8
5
|
module Ecdsa
|
|
9
|
-
|
|
10
6
|
def self.sign(message, privateKey, hashfunc=nil)
|
|
11
|
-
if hashfunc.nil?
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
if hashfunc.nil? then hashfunc = lambda{ |x| Digest::SHA256.digest(x) } end
|
|
8
|
+
curve = privateKey.curve
|
|
9
|
+
byteMessage = hashfunc.call(message)
|
|
10
|
+
numberMessage = Utils::Binary.numberFromByteString(byteMessage, curve.nBitLength)
|
|
11
|
+
|
|
12
|
+
r, s, randSignPoint = 0, 0, nil
|
|
13
|
+
kIterator = Utils::RandomInteger.rfc6979(byteMessage, privateKey.secret, curve, hashfunc)
|
|
14
|
+
while r == 0 or s == 0
|
|
15
|
+
randNum = kIterator.next
|
|
16
|
+
randSignPoint = Math.multiplyGenerator(curve, randNum)
|
|
17
|
+
r = randSignPoint.x % curve.n
|
|
18
|
+
s = ((numberMessage + r * privateKey.secret) * (Math.inv(randNum, curve.n))) % curve.n
|
|
19
|
+
end
|
|
20
|
+
recoveryId = randSignPoint.y & 1
|
|
21
|
+
if randSignPoint.y > curve.n
|
|
22
|
+
recoveryId += 2
|
|
23
|
+
end
|
|
24
|
+
if s > curve.n / 2
|
|
25
|
+
s = curve.n - s
|
|
26
|
+
recoveryId ^= 1
|
|
15
27
|
end
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
return Signature.new(signature)
|
|
29
|
+
return Signature.new(r, s, recoveryId)
|
|
19
30
|
end
|
|
20
31
|
|
|
21
32
|
def self.verify(message, signature, publicKey, hashfunc=nil)
|
|
22
|
-
if hashfunc.nil?
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
if hashfunc.nil? then hashfunc = lambda{ |x| Digest::SHA256.digest(x) } end
|
|
34
|
+
curve = publicKey.curve
|
|
35
|
+
byteMessage = hashfunc.call(message)
|
|
36
|
+
numberMessage = Utils::Binary.numberFromByteString(byteMessage, curve.nBitLength)
|
|
37
|
+
|
|
38
|
+
r = signature.r
|
|
39
|
+
s = signature.s
|
|
40
|
+
|
|
41
|
+
if not (1 <= r and r <= curve.n - 1)
|
|
42
|
+
return false
|
|
26
43
|
end
|
|
27
|
-
|
|
44
|
+
if not (1 <= s and s <= curve.n - 1)
|
|
45
|
+
return false
|
|
46
|
+
end
|
|
47
|
+
if not curve.contains(publicKey.point)
|
|
48
|
+
return false
|
|
49
|
+
end
|
|
50
|
+
inv = Math.inv(s, curve.n)
|
|
51
|
+
v = Math.multiplyAndAdd(
|
|
52
|
+
curve.g, (numberMessage * inv) % curve.n,
|
|
53
|
+
publicKey.point, (r * inv) % curve.n,
|
|
54
|
+
curve.n, curve.a, curve.p, curve,
|
|
55
|
+
)
|
|
56
|
+
if v.isAtInfinity
|
|
57
|
+
return false
|
|
58
|
+
end
|
|
59
|
+
return v.x % curve.n == r
|
|
28
60
|
end
|
|
29
|
-
|
|
30
61
|
end
|
|
31
|
-
|
|
32
|
-
end
|
|
62
|
+
end
|