bitcoin-addrgen 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|