ecdsa_ext 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: fa41cad7e597e74cfabf27c0dd026aa60b47f64419d8c17e56653fe68d863e4c
|
4
|
+
data.tar.gz: 35754ec99989184df9f3ceabdf2d6c946ed55d810e0753b34b3a9779aa04eb1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0f9f06b62b6ca56b4c374d665f600d3750204b9b3a91651069f4416a08869c58148158c53cc9b981c3508703c3451b93541c4dbbe72f43cda4364c03ffbd507
|
7
|
+
data.tar.gz: 26f3e2e7313ff913d4b03b91ac3bcc0daa17ca3d8c2f1b3f43a049140f7fd9ba367ccad84913882decdbacc2a06304e40ae3a3add342b86103e980d5df341257
|
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
|
+
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.0
|
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
|