bitcoin-addrgen 0.0.1 → 0.0.2
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.
- data/Gemfile.lock +3 -3
- data/bitcoin-addrgen.gemspec +1 -1
- data/lib/bitcoin_addrgen/addrgen.rb +150 -51
- data/lib/bitcoin_addrgen/version.rb +1 -1
- metadata +5 -5
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bitcoin-addrgen (0.0.
|
5
|
-
|
4
|
+
bitcoin-addrgen (0.0.2)
|
5
|
+
ffi (~> 1.2.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
10
|
diff-lcs (1.2.4)
|
11
|
-
|
11
|
+
ffi (1.9.0)
|
12
12
|
rake (10.0.4)
|
13
13
|
rspec (2.13.0)
|
14
14
|
rspec-core (~> 2.13.0)
|
data/bitcoin-addrgen.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_dependency '
|
21
|
+
s.add_dependency 'ffi', '~> 1.2.0'
|
22
22
|
s.add_development_dependency 'rspec', '~> 2.13.0'
|
23
23
|
s.add_development_dependency 'rake', '~> 10.0.4'
|
24
24
|
end
|
@@ -22,7 +22,115 @@
|
|
22
22
|
# OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
24
|
require 'digest'
|
25
|
-
require '
|
25
|
+
require 'ffi'
|
26
|
+
|
27
|
+
module GMP
|
28
|
+
extend FFI::Library
|
29
|
+
ffi_lib ['gmp', 'libgmp.so.3', 'libgmp.so.10']
|
30
|
+
attach_function :__gmpz_init_set_str, [:pointer, :string, :int], :int
|
31
|
+
attach_function :__gmpz_get_str, [:string, :int, :pointer], :string
|
32
|
+
attach_function :__gmpz_add, [:pointer, :pointer, :pointer], :void
|
33
|
+
attach_function :__gmpz_add_ui, [:pointer, :pointer, :ulong], :void
|
34
|
+
attach_function :__gmpz_and, [:pointer, :pointer, :pointer], :void
|
35
|
+
attach_function :__gmpz_cmp, [:pointer, :pointer], :int
|
36
|
+
attach_function :__gmpz_cmp_si, [:pointer, :long], :int
|
37
|
+
attach_function :__gmpz_fdiv_q_ui, [:pointer, :pointer, :ulong], :ulong
|
38
|
+
attach_function :__gmpz_fdiv_r, [:pointer, :pointer, :pointer], :void
|
39
|
+
attach_function :__gmpz_invert, [:pointer, :pointer, :pointer], :int
|
40
|
+
attach_function :__gmpz_mul, [:pointer, :pointer, :pointer], :void
|
41
|
+
attach_function :__gmpz_mul_si, [:pointer, :pointer, :long], :void
|
42
|
+
attach_function :__gmpz_neg, [:pointer, :pointer], :void
|
43
|
+
attach_function :__gmpz_pow_ui, [:pointer, :pointer, :ulong], :void
|
44
|
+
attach_function :__gmpz_sub, [:pointer, :pointer, :pointer], :void
|
45
|
+
end
|
46
|
+
|
47
|
+
def gmp_init(str, base)
|
48
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
49
|
+
GMP::__gmpz_init_set_str(ptr, str, base)
|
50
|
+
ptr
|
51
|
+
end
|
52
|
+
|
53
|
+
def gmp_strval(op, base)
|
54
|
+
GMP::__gmpz_get_str(nil, base, op)
|
55
|
+
end
|
56
|
+
|
57
|
+
def gmp_add(a, b)
|
58
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
59
|
+
if a.instance_of? Fixnum
|
60
|
+
GMP::__gmpz_add_ui(ptr, b, a)
|
61
|
+
elsif b.instance_of? Fixnum
|
62
|
+
GMP::__gmpz_add_ui(ptr, a, b)
|
63
|
+
else
|
64
|
+
GMP::__gmpz_add(ptr, a, b)
|
65
|
+
end
|
66
|
+
ptr
|
67
|
+
end
|
68
|
+
|
69
|
+
def gmp_and(a, b)
|
70
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
71
|
+
GMP::__gmpz_and(ptr, a, b)
|
72
|
+
ptr
|
73
|
+
end
|
74
|
+
|
75
|
+
def gmp_cmp(a, b)
|
76
|
+
if a.instance_of? Fixnum and b.instance_of? Fixnum
|
77
|
+
a <=> b
|
78
|
+
elsif a.instance_of? Fixnum
|
79
|
+
-GMP::__gmpz_cmp_si(b, a)
|
80
|
+
elsif b.instance_of? Fixnum
|
81
|
+
GMP::__gmpz_cmp_si(a, b)
|
82
|
+
else
|
83
|
+
GMP::__gmpz_cmp(a, b)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def gmp_div(a, b)
|
88
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
89
|
+
GMP::__gmpz_fdiv_q_ui(ptr, a, b)
|
90
|
+
ptr
|
91
|
+
end
|
92
|
+
|
93
|
+
def gmp_invert(a, b)
|
94
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
95
|
+
GMP::__gmpz_invert(ptr, a, b)
|
96
|
+
ptr
|
97
|
+
end
|
98
|
+
|
99
|
+
def gmp_mod(a, b)
|
100
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
101
|
+
GMP::__gmpz_fdiv_r(ptr, a, b)
|
102
|
+
ptr
|
103
|
+
end
|
104
|
+
|
105
|
+
def gmp_mul(a, b)
|
106
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
107
|
+
if a.instance_of? Fixnum
|
108
|
+
GMP::__gmpz_mul_si(ptr, b, a)
|
109
|
+
elsif b.instance_of? Fixnum
|
110
|
+
GMP::__gmpz_mul_si(ptr, a, b)
|
111
|
+
else
|
112
|
+
GMP::__gmpz_mul(ptr, a, b)
|
113
|
+
end
|
114
|
+
ptr
|
115
|
+
end
|
116
|
+
|
117
|
+
def gmp_neg(a)
|
118
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
119
|
+
GMP::__gmpz_neg(ptr, a)
|
120
|
+
ptr
|
121
|
+
end
|
122
|
+
|
123
|
+
def gmp_pow(a, b)
|
124
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
125
|
+
GMP::__gmpz_pow_ui(ptr, a, b)
|
126
|
+
ptr
|
127
|
+
end
|
128
|
+
|
129
|
+
def gmp_sub(a, b)
|
130
|
+
ptr = FFI::MemoryPointer.new :char, 16
|
131
|
+
GMP::__gmpz_sub(ptr, a, b)
|
132
|
+
ptr
|
133
|
+
end
|
26
134
|
|
27
135
|
module BitcoinAddrgen
|
28
136
|
class Curve
|
@@ -36,15 +144,11 @@ module BitcoinAddrgen
|
|
36
144
|
end
|
37
145
|
|
38
146
|
def contains(x, y)
|
39
|
-
|
147
|
+
gmp_cmp(gmp_mod(gmp_sub(gmp_pow(y, 2), gmp_add(gmp_add(gmp_pow(x, 3), gmp_mul(@a, x)), @b)), @prime), 0) == 0
|
40
148
|
end
|
41
149
|
|
42
150
|
def self.cmp(cp1, cp2)
|
43
|
-
|
44
|
-
return 0
|
45
|
-
else
|
46
|
-
return 1
|
47
|
-
end
|
151
|
+
gmp_cmp(cp1.a, cp2.a) or gmp_cmp(cp1.b, cp.b) or gmp_cmp(cp.prime, cp.prime)
|
48
152
|
end
|
49
153
|
|
50
154
|
end
|
@@ -59,7 +163,7 @@ module BitcoinAddrgen
|
|
59
163
|
@y = y
|
60
164
|
@order = order
|
61
165
|
if @curve and @curve.instance_of?(Curve)
|
62
|
-
raise Exception, 'Curve does not contain point' if
|
166
|
+
raise Exception, 'Curve does not contain point' if not @curve.contains(@x, @y)
|
63
167
|
if @order != nil
|
64
168
|
raise Exception, 'Self*Order must equal infinity' if (Point.cmp(Point.mul(order, self), :infinity) != 0)
|
65
169
|
end
|
@@ -75,11 +179,7 @@ module BitcoinAddrgen
|
|
75
179
|
return 1 if p1.instance_of?(Point)
|
76
180
|
return 0 if !p1.instance_of?(Point)
|
77
181
|
end
|
78
|
-
|
79
|
-
return 0
|
80
|
-
else
|
81
|
-
return 1
|
82
|
-
end
|
182
|
+
gmp_cmp(p1.x, p2.x) or gmp_cmp(p1.y, p2.y) or Curve.cmp(p1.curve, p2.curve)
|
83
183
|
end
|
84
184
|
|
85
185
|
def self.add(p1, p2)
|
@@ -89,17 +189,17 @@ module BitcoinAddrgen
|
|
89
189
|
return :infinity if Point.cmp(p1, :infinity) == 0 and Point.cmp(p2, :infinity) == 0
|
90
190
|
|
91
191
|
if Curve.cmp(p1.curve, p2.curve) == 0
|
92
|
-
if p1.x
|
93
|
-
if (p1.y
|
192
|
+
if gmp_cmp(p1.x, p2.x) == 0
|
193
|
+
if gmp_mod(gmp_add(p1.y, p2.y), p1.curve.prime) == 0
|
94
194
|
return :infinity
|
95
195
|
else
|
96
196
|
return Point.double(p1)
|
97
197
|
end
|
98
198
|
end
|
99
199
|
p = p1.curve.prime
|
100
|
-
l = (p2.y
|
101
|
-
x3 = (l
|
102
|
-
y3 = (l
|
200
|
+
l = gmp_mul(gmp_sub(p2.y, p1.y), gmp_invert(gmp_sub(p2.x, p1.x), p))
|
201
|
+
x3 = gmp_mod(gmp_sub(gmp_sub(gmp_pow(l, 2), p1.x), p2.x), p)
|
202
|
+
y3 = gmp_mod(gmp_sub(gmp_mul(l, gmp_sub(p1.x, x3)), p1.y), p)
|
103
203
|
p3 = Point.new(p1.curve, x3, y3)
|
104
204
|
return p3
|
105
205
|
else
|
@@ -110,44 +210,43 @@ module BitcoinAddrgen
|
|
110
210
|
def self.mul(x2, p1)
|
111
211
|
e = x2
|
112
212
|
return :infinity if Point.cmp(p1, :infinity) == 0
|
113
|
-
e = e
|
114
|
-
return :infinity if e ==
|
115
|
-
if e >
|
116
|
-
e3 = 3
|
117
|
-
negative_self = Point.new(p1.curve, p1.x,
|
118
|
-
i = Point.leftmost_bit(e3)
|
213
|
+
e = gmp_mod(e, p1.order) if p1.order != nil
|
214
|
+
return :infinity if gmp_cmp(e, 0) == 0
|
215
|
+
if gmp_cmp(e, 0) > 0
|
216
|
+
e3 = gmp_mul(3, e)
|
217
|
+
negative_self = Point.new(p1.curve, p1.x, gmp_neg(p1.y), p1.order)
|
218
|
+
i = gmp_div(Point.leftmost_bit(e3), 2)
|
119
219
|
result = p1
|
120
|
-
while i >
|
220
|
+
while gmp_cmp(i, 1) > 0
|
121
221
|
result = Point.double(result)
|
122
|
-
result = Point.add(result, p1) if (e3
|
123
|
-
result = Point.add(result, negative_self) if (e3
|
124
|
-
i = i
|
222
|
+
result = Point.add(result, p1) if gmp_cmp(gmp_and(e3, i), 0) != 0 and gmp_cmp(gmp_and(e, i), 0) == 0
|
223
|
+
result = Point.add(result, negative_self) if gmp_cmp(gmp_and(e3, i), 0) == 0 and gmp_cmp(gmp_and(e, i), 0) != 0
|
224
|
+
i = gmp_div(i, 2)
|
125
225
|
end
|
126
226
|
return result
|
127
227
|
end
|
128
228
|
end
|
129
229
|
|
130
230
|
def self.leftmost_bit(x)
|
131
|
-
if x >
|
132
|
-
result =
|
133
|
-
while result <=
|
134
|
-
result
|
231
|
+
if gmp_cmp(x, 0) > 0
|
232
|
+
result = gmp_init('1', 10)
|
233
|
+
while gmp_cmp(result, x) <= 0
|
234
|
+
result = gmp_mul(2, result)
|
135
235
|
end
|
136
|
-
return result
|
236
|
+
return gmp_div(result, 2)
|
137
237
|
end
|
138
238
|
end
|
139
239
|
|
140
240
|
def self.double(p1)
|
141
241
|
p = p1.curve.prime
|
142
242
|
a = p1.curve.a
|
143
|
-
inverse = (2
|
144
|
-
three_x2 = 3
|
145
|
-
l = ((three_x2
|
146
|
-
x3 = (l
|
147
|
-
y3 = (l
|
148
|
-
y3 = p
|
149
|
-
|
150
|
-
p3
|
243
|
+
inverse = gmp_invert(gmp_mul(2, p1.y), p)
|
244
|
+
three_x2 = gmp_mul(3, gmp_pow(p1.x, 2))
|
245
|
+
l = gmp_mod(gmp_mul(gmp_add(three_x2, a), inverse), p)
|
246
|
+
x3 = gmp_mod(gmp_sub(gmp_pow(l, 2), gmp_mul(2, p1.x)), p)
|
247
|
+
y3 = gmp_mod(gmp_sub(gmp_mul(l, gmp_sub(p1.x, x3)), p1.y), p)
|
248
|
+
y3 = gmp_add(p, y3) if (gmp_cmp(0, y3) > 0)
|
249
|
+
return Point.new(p1.curve, x3, y3)
|
151
250
|
end
|
152
251
|
|
153
252
|
end
|
@@ -170,26 +269,26 @@ module BitcoinAddrgen
|
|
170
269
|
end
|
171
270
|
|
172
271
|
def self.addr_from_mpk(mpk, idx)
|
173
|
-
_p =
|
174
|
-
_r =
|
175
|
-
_b =
|
176
|
-
_Gx =
|
177
|
-
_Gy =
|
272
|
+
_p = gmp_init('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16)
|
273
|
+
_r = gmp_init('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16)
|
274
|
+
_b = gmp_init('0000000000000000000000000000000000000000000000000000000000000007', 16)
|
275
|
+
_Gx = gmp_init('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16)
|
276
|
+
_Gy = gmp_init('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16)
|
178
277
|
curve = Curve.new(_p, 0, _b)
|
179
278
|
gen = Point.new(curve, _Gx, _Gy, _r)
|
180
279
|
|
181
280
|
# prepare the input values
|
182
|
-
x =
|
183
|
-
y =
|
184
|
-
z =
|
281
|
+
x = gmp_init(mpk[0, 64], 16)
|
282
|
+
y = gmp_init(mpk[64, 64], 16)
|
283
|
+
z = gmp_init(sha256(sha256_raw(idx.to_s + ':0:' + hex_to_bin(mpk))), 16)
|
185
284
|
|
186
285
|
# generate the new public key based off master and sequence points
|
187
286
|
pt = Point.add(Point.new(curve, x, y), Point.mul(z, gen))
|
188
|
-
keystr = hex_to_bin('04' + pt.x
|
287
|
+
keystr = hex_to_bin('04' + gmp_strval(pt.x, 16).rjust(64, '0') + gmp_strval(pt.y, 16).rjust(64, '0'))
|
189
288
|
vh160 = '00' + ripemd160(sha256_raw(keystr))
|
190
289
|
addr = vh160 + sha256(sha256_raw(hex_to_bin(vh160)))[0, 8]
|
191
290
|
|
192
|
-
num =
|
291
|
+
num = gmp_strval(gmp_init(addr, 16), 58)
|
193
292
|
num = num.tr('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv', '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz')
|
194
293
|
|
195
294
|
pad = ''
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitcoin-addrgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,16 +9,16 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: ffi
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 1.2.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: rspec
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|