ecdsa_ext 0.2.1 → 0.3.1
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/Gemfile +3 -1
- data/README.md +8 -1
- data/ecdsa_ext.gemspec +1 -1
- data/lib/ecdsa/ext/jacobian_arithmetic.rb +86 -0
- data/lib/ecdsa/ext/jacobian_point.rb +195 -0
- data/lib/ecdsa/ext/point.rb +6 -0
- data/lib/ecdsa/ext/{point_arithmetic.rb → projective_arithmetic.rb} +4 -4
- data/lib/ecdsa/ext/projective_point.rb +2 -2
- data/lib/ecdsa/ext/version.rb +1 -1
- data/lib/ecdsa/ext.rb +3 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2a5e0f4a0a8de441e3d2f1374666b345b3b5576c4d3b455b1e138ee9c032c88
|
4
|
+
data.tar.gz: 844a766b56bf77ce971788fa414194500f9e9ee25c9549b003cded0437fb2ff4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 794aaac69e3cad831d943aa488d0b3a5f9169d7660dd3c37edb284332550be3112b39455090af2efc0229ac828d72280ad827c383e6c29300ad2d29febc28bfc
|
7
|
+
data.tar.gz: 5ee76f7e334da633becd188573089f00e3c326726217da25ceb7fb3a9e04279e5548a4085f64366bb8e530b986fdd8f691360a88690dfbc889f90333aea45314
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -75,4 +75,11 @@ projective_point4_neg = projective_point4.negate
|
|
75
75
|
require 'ecdsa_ext'
|
76
76
|
|
77
77
|
affine_point = projective_point4.to_affine
|
78
|
-
```
|
78
|
+
```
|
79
|
+
|
80
|
+
### Use jacobian coordinates
|
81
|
+
|
82
|
+
Jacobian coordinates have been supported since 0.3.0.
|
83
|
+
|
84
|
+
When using Jacobian coordinates, use `ECDSA::Ext::JacobianPoint` instead of `ECDSA::Ext::ProjectivePoint`.
|
85
|
+
In addition, `ECDSA::Point` now has a `to_jacobian` method that convert affine coordinates to jacobian coordinates.
|
data/ecdsa_ext.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
23
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
24
|
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
25
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features|bench)/|\.(?:git|travis|circleci)|appveyor)})
|
26
26
|
end
|
27
27
|
end
|
28
28
|
spec.bindir = "exe"
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ECDSA
|
3
|
+
module Ext
|
4
|
+
# Point arithmetic implementation
|
5
|
+
module JacobianArithmetic
|
6
|
+
def add_with_z_one(a, b)
|
7
|
+
field = a.field
|
8
|
+
h = field.mod(b.x - a.x)
|
9
|
+
hh = field.square(h)
|
10
|
+
i = field.mod(4 * hh)
|
11
|
+
j = field.mod(h * i)
|
12
|
+
r = field.mod(2 * (b.y - a.y))
|
13
|
+
return double_with_z_one(a) if h.zero? && r.zero?
|
14
|
+
v = field.mod(a.x * i)
|
15
|
+
x3 = field.mod(field.square(r) - j - 2 * v)
|
16
|
+
y3 = field.mod(r * (v - x3) - 2 * a.y * j)
|
17
|
+
z3 = field.mod(2 * h)
|
18
|
+
JacobianPoint.new(a.group, x3, y3, z3)
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_with_z_eq(a, b)
|
22
|
+
field = a.field
|
23
|
+
a = field.square(field.mod(b.x - a.x))
|
24
|
+
b = field.mod(a.x * a)
|
25
|
+
c = field.mod(b.x * a)
|
26
|
+
d = field.square(field.mod(b.y - a.y))
|
27
|
+
return double(a) if a.zero? && d.zero?
|
28
|
+
x3 = field.mod(d - b - c)
|
29
|
+
y3 = field.mod((b.y - a.y) * (b - x3) - a.y * (c - b))
|
30
|
+
z3 = field.mod(a.z * (b.x - a.x))
|
31
|
+
JacobianPoint.new(a.group, x3, y3, z3)
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_with_z2_one(a, b)
|
35
|
+
field = a.field
|
36
|
+
z1z1 = field.square(a.z)
|
37
|
+
u2 = field.mod(b.x * z1z1)
|
38
|
+
s2 = field.mod(b.y * a.z * z1z1)
|
39
|
+
h = field.mod(u2 - a.x)
|
40
|
+
hh = field.square(h)
|
41
|
+
i = field.mod(4 * hh)
|
42
|
+
j = field.mod(h * i)
|
43
|
+
r = field.mod(2 * (s2 - a.y))
|
44
|
+
return double_with_z_one(b) if r.zero? && h.zero?
|
45
|
+
v = field.mod(a.x * i)
|
46
|
+
x3 = field.mod(r * r - j - 2 * v)
|
47
|
+
y3 = field.mod(r * (v - x3) - 2 * a.y * j)
|
48
|
+
z3 = field.mod(field.square(a.z + h) - z1z1 - hh)
|
49
|
+
JacobianPoint.new(a.group, x3, y3, z3)
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_with_z_ne(a, b)
|
53
|
+
field = a.field
|
54
|
+
z1z1 = field.square(a.z)
|
55
|
+
z2z2 = field.square(b.z)
|
56
|
+
u1 = field.mod(a.x * z2z2)
|
57
|
+
u2 = field.mod(b.x * z1z1)
|
58
|
+
s1 = field.mod(a.y * b.z * z2z2)
|
59
|
+
s2 = field.mod(b.y * a.z * z1z1)
|
60
|
+
h = field.mod(u2 - u1)
|
61
|
+
i = field.mod(4 * h * h)
|
62
|
+
j = field.mod(h * i)
|
63
|
+
r = field.mod(2 * (s2 - s1))
|
64
|
+
return double(a) if h.zero? && r.zero?
|
65
|
+
v = field.mod(u1 * i)
|
66
|
+
x3 = field.mod(r * r - j - 2 * v)
|
67
|
+
y3 = field.mod(r * (v - x3) - 2 * s1 * j)
|
68
|
+
z3 = field.mod((field.square(a.z + b.z) - z1z1 - z2z2) * h)
|
69
|
+
JacobianPoint.new(a.group, x3, y3, z3)
|
70
|
+
end
|
71
|
+
|
72
|
+
def double_with_z_one(point)
|
73
|
+
field = point.field
|
74
|
+
xx = field.square(point.x)
|
75
|
+
yy = field.square(point.y)
|
76
|
+
yyyy = field.square(yy)
|
77
|
+
s = field.mod(2 * (field.square(point.x + yy) - xx - yyyy))
|
78
|
+
m = field.mod(3 * xx + point.group.param_a)
|
79
|
+
t = field.mod(m * m - 2 * s)
|
80
|
+
y3 = field.mod(m * (s - t) - 8 * yyyy)
|
81
|
+
z3 = field.mod(2 * point.y)
|
82
|
+
JacobianPoint.new(point.group, t, y3, z3)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ECDSA
|
4
|
+
module Ext
|
5
|
+
# Point of Jacobian coordinates
|
6
|
+
class JacobianPoint
|
7
|
+
include JacobianArithmetic
|
8
|
+
|
9
|
+
attr_reader :group, :x, :y, :z
|
10
|
+
|
11
|
+
# Create new instance of jacobian
|
12
|
+
# @param [ECDSA::Group] group
|
13
|
+
# @param [Array] args [x, y, z]
|
14
|
+
# @return [ECDSA::Ext::ProjectivePoint]
|
15
|
+
def initialize(group, *args)
|
16
|
+
@group = group
|
17
|
+
@x, @y, @z = args
|
18
|
+
raise ArgumentError, "Invalid x: #{x.inspect}" unless x.is_a?(Integer)
|
19
|
+
raise ArgumentError, "Invalid y: #{y.inspect}" unless y.is_a?(Integer)
|
20
|
+
raise ArgumentError, "Invalid z: #{z.inspect}" unless z.is_a?(Integer)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get filed of this group.
|
24
|
+
# @return [ECDSA::PrimeField]
|
25
|
+
def field
|
26
|
+
group.field
|
27
|
+
end
|
28
|
+
|
29
|
+
# Convert coordinates from affine to projective.
|
30
|
+
# @param [ECDSA::Point] point
|
31
|
+
# @return [ECDSA::Ext::JacobianPoint]
|
32
|
+
def self.from_affine(point)
|
33
|
+
if point.infinity?
|
34
|
+
JacobianPoint.infinity(point.group)
|
35
|
+
else
|
36
|
+
new(point.group, point.x, point.y, 1)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Create infinity point
|
41
|
+
# @return [ECDSA::Ext::JacobianPoint]
|
42
|
+
def self.infinity(group)
|
43
|
+
# new(group, :infinity)
|
44
|
+
new(group, 0, 1, 0)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Check whether infinity point or not.
|
48
|
+
# @return [Boolean]
|
49
|
+
def infinity?
|
50
|
+
x.zero? && y == 1 && z.zero?
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add this point to another point on the same curve.
|
54
|
+
# @param [ECDSA::Ext::JacobianPoint] other
|
55
|
+
# @return [ECDSA::Ext::JacobianPoint]
|
56
|
+
def add_to_point(other)
|
57
|
+
unless other.is_a?(JacobianPoint)
|
58
|
+
raise ArgumentError, "other point must be instance of JacobianPoint"
|
59
|
+
end
|
60
|
+
unless other.group == group
|
61
|
+
raise ArgumentError, "other group must be same group of this point"
|
62
|
+
end
|
63
|
+
|
64
|
+
return other if infinity?
|
65
|
+
return self if other.infinity?
|
66
|
+
|
67
|
+
if x == other.x && y == field.mod(-other.y) && z == other.z
|
68
|
+
return JacobianPoint.infinity(group)
|
69
|
+
end
|
70
|
+
|
71
|
+
return other if y.zero? || z.zero?
|
72
|
+
return self if other.y.zero? || other.z.zero?
|
73
|
+
|
74
|
+
unless x == other.x
|
75
|
+
if z == other.z
|
76
|
+
return(
|
77
|
+
z == 1 ? add_with_z_one(self, other) : add_with_z_eq(self, other)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
return add_with_z2_one(other, self) if z == 1
|
81
|
+
return add_with_z2_one(self, other) if other.z == 1
|
82
|
+
return add_with_z_ne(self, other)
|
83
|
+
end
|
84
|
+
|
85
|
+
return double if self == other
|
86
|
+
raise "Failed to add #{inspect} to #{other.inspect}: No addition rules matched."
|
87
|
+
end
|
88
|
+
alias + add_to_point
|
89
|
+
|
90
|
+
# Return the point added to itself.
|
91
|
+
# @return [ECDSA::Ext::JacobianPoint]
|
92
|
+
def double
|
93
|
+
return self if infinity?
|
94
|
+
|
95
|
+
return double_with_z_one(self) if z == 1
|
96
|
+
|
97
|
+
xx = field.square(x)
|
98
|
+
yy = field.square(y)
|
99
|
+
yyyy = field.square(yy)
|
100
|
+
zz = field.square(z)
|
101
|
+
s = field.mod(2 * (field.square(x + yy) - xx - yyyy))
|
102
|
+
m = field.mod(3 * xx + group.param_a * zz * zz)
|
103
|
+
t = field.mod(m * m - 2 * s)
|
104
|
+
y3 = field.mod(m * (s - t) - 8 * yyyy)
|
105
|
+
z3 = field.mod(field.square(y + z) - yy - zz)
|
106
|
+
JacobianPoint.new(group, t, y3, z3)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Return the point multiplied by a non-negative integer.
|
110
|
+
# @param [Integer] x
|
111
|
+
# @return [ECDSA::Ext::JacobianPoint]
|
112
|
+
def multiply_by_scalar(x)
|
113
|
+
raise ArgumentError, "Scalar is not an integer." unless x.is_a?(Integer)
|
114
|
+
raise ArgumentError, "Scalar is negative." if x.negative?
|
115
|
+
|
116
|
+
q = JacobianPoint.infinity(group)
|
117
|
+
v = self
|
118
|
+
i = x
|
119
|
+
while i.positive?
|
120
|
+
q = q.add_to_point(v) if i.odd?
|
121
|
+
v = v.double
|
122
|
+
i >>= 1
|
123
|
+
end
|
124
|
+
q
|
125
|
+
end
|
126
|
+
alias * multiply_by_scalar
|
127
|
+
|
128
|
+
# Convert this coordinates to affine coordinates.
|
129
|
+
# @return [ECDSA::Point]
|
130
|
+
def to_affine
|
131
|
+
if infinity?
|
132
|
+
group.infinity
|
133
|
+
else
|
134
|
+
z_inv = field.inverse(z)
|
135
|
+
tmp_z = field.square(z_inv)
|
136
|
+
new_x = field.mod(x * tmp_z) # x = x * (1/z)^2
|
137
|
+
new_y = field.mod(y * tmp_z * z_inv) # y = y * (1/z)^3
|
138
|
+
ECDSA::Point.new(group, new_x, new_y)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Return additive inverse of the point.
|
143
|
+
# @return [ECDSA::Ext::ProjectivePoint]
|
144
|
+
def negate
|
145
|
+
return self if infinity?
|
146
|
+
ProjectivePoint.new(group, x, field.mod(-y), z)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Return coordinates.
|
150
|
+
# @return [Array] (x, y , z)
|
151
|
+
def coords
|
152
|
+
[x, y, z]
|
153
|
+
end
|
154
|
+
|
155
|
+
# Check whether same jacobian point or not.
|
156
|
+
# @param [ECDSA::Ext::JacobianPoint] other
|
157
|
+
# @return [Boolean]
|
158
|
+
def ==(other)
|
159
|
+
return false unless other.is_a?(JacobianPoint)
|
160
|
+
return true if infinity? && other.infinity?
|
161
|
+
|
162
|
+
zz = field.square(z)
|
163
|
+
other_zz = field.square(other.z)
|
164
|
+
lhs_x = field.mod(x * other_zz)
|
165
|
+
rhs_x = field.mod(other.x * zz)
|
166
|
+
lhs_y = field.mod(y * other_zz * other.z)
|
167
|
+
rhs_y = field.mod(other.y * zz * z)
|
168
|
+
|
169
|
+
lhs_x == rhs_x && lhs_y == rhs_y
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def double_non_const
|
175
|
+
return self if infinity?
|
176
|
+
z == 1 ? double_z1 : double
|
177
|
+
end
|
178
|
+
|
179
|
+
def double_z1
|
180
|
+
z3 = field.mod(2 * y)
|
181
|
+
a = field.square(x)
|
182
|
+
b = field.square(y)
|
183
|
+
c = field.square(b)
|
184
|
+
b = field.square(x + b)
|
185
|
+
d = field.mod(2 * (b - (a + c)))
|
186
|
+
e = field.mod(a * 3)
|
187
|
+
f = field.square(e)
|
188
|
+
x3 = field.mod(f - (2 * d))
|
189
|
+
f = field.mod(d - x3)
|
190
|
+
y3 = field.mod(e * f - 8 * c)
|
191
|
+
JacobianPoint.new(group, x3, y3, z3)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
data/lib/ecdsa/ext/point.rb
CHANGED
@@ -8,5 +8,11 @@ module ECDSA
|
|
8
8
|
def to_projective
|
9
9
|
ECDSA::Ext::ProjectivePoint.from_affine(self)
|
10
10
|
end
|
11
|
+
|
12
|
+
# Convert coordinates to projective point.
|
13
|
+
# @return [ECDSA::Ext::JacobianPoint]
|
14
|
+
def to_jacobian
|
15
|
+
ECDSA::Ext::JacobianPoint.from_affine(self)
|
16
|
+
end
|
11
17
|
end
|
12
18
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
module ECDSA
|
3
3
|
module Ext
|
4
4
|
# Point arithmetic implementation
|
5
|
-
module
|
5
|
+
module ProjectiveArithmetic
|
6
6
|
def addition_negative3(a, b)
|
7
7
|
field = a.field
|
8
8
|
xx = field.mod(a.x * b.x)
|
@@ -76,9 +76,9 @@ module ECDSA
|
|
76
76
|
|
77
77
|
def double_negative3(point)
|
78
78
|
field = point.field
|
79
|
-
xx = field.
|
80
|
-
yy = field.
|
81
|
-
zz = field.
|
79
|
+
xx = field.square(point.x)
|
80
|
+
yy = field.square(point.y)
|
81
|
+
zz = field.square(point.z)
|
82
82
|
xy2 = field.mod(point.x * point.y * 2)
|
83
83
|
xz2 = field.mod(point.x * point.z * 2)
|
84
84
|
|
@@ -4,13 +4,13 @@ module ECDSA
|
|
4
4
|
module Ext
|
5
5
|
# Representing a point on elliptic curves using projective coordinates.
|
6
6
|
class ProjectivePoint
|
7
|
-
include
|
7
|
+
include ProjectiveArithmetic
|
8
8
|
|
9
9
|
attr_reader :group, :x, :y, :z
|
10
10
|
|
11
11
|
# Create new instance of projective
|
12
12
|
# @param [ECDSA::Group] group
|
13
|
-
# @param [Array] args [
|
13
|
+
# @param [Array] args [x, y, z]
|
14
14
|
# @return [ECDSA::Ext::ProjectivePoint]
|
15
15
|
def initialize(group, *args)
|
16
16
|
@group = group
|
data/lib/ecdsa/ext/version.rb
CHANGED
data/lib/ecdsa/ext.rb
CHANGED
@@ -4,7 +4,9 @@ require_relative "ext/point"
|
|
4
4
|
module ECDSA
|
5
5
|
# Extension for ecdsa gem.
|
6
6
|
module Ext
|
7
|
-
autoload :
|
7
|
+
autoload :ProjectiveArithmetic, "ecdsa/ext/projective_arithmetic"
|
8
8
|
autoload :ProjectivePoint, "ecdsa/ext/projective_point"
|
9
|
+
autoload :JacobianArithmetic, "ecdsa/ext/jacobian_arithmetic"
|
10
|
+
autoload :JacobianPoint, "ecdsa/ext/jacobian_point"
|
9
11
|
end
|
10
12
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecdsa_ext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ecdsa
|
@@ -46,8 +46,10 @@ files:
|
|
46
46
|
- bin/setup
|
47
47
|
- ecdsa_ext.gemspec
|
48
48
|
- lib/ecdsa/ext.rb
|
49
|
+
- lib/ecdsa/ext/jacobian_arithmetic.rb
|
50
|
+
- lib/ecdsa/ext/jacobian_point.rb
|
49
51
|
- lib/ecdsa/ext/point.rb
|
50
|
-
- lib/ecdsa/ext/
|
52
|
+
- lib/ecdsa/ext/projective_arithmetic.rb
|
51
53
|
- lib/ecdsa/ext/projective_point.rb
|
52
54
|
- lib/ecdsa/ext/version.rb
|
53
55
|
- lib/ecdsa_ext.rb
|