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.
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bitcoin-addrgen (0.0.1)
5
- gmp (~> 0.6.0)
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
- gmp (0.6.31)
11
+ ffi (1.9.0)
12
12
  rake (10.0.4)
13
13
  rspec (2.13.0)
14
14
  rspec-core (~> 2.13.0)
@@ -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 'gmp', '~> 0.6.0'
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 'gmp'
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
- GMP::Z.new(0) == (y**2 - (x ** 3 + @a * x + @b)).fmod(@prime)
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
- if cp1.a == cp2.a and cp1.b == cp2.b and cp1.prime == cp2.prime
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 !@curve.contains(@x, @y)
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
- if p1.x == p2.x and p1.y == p2.y and Curve.cmp(p1.curve, p2.curve)
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 == p2.x
93
- if (p1.y + p2.y).fmod(p1.curve.prime) == 0
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 - p1.y) * (p2.x - p1.x).invert(p)
101
- x3 = (l ** 2 - p1.x - p2.x).fmod(p)
102
- y3 = (l * (p1.x - x3) - p1.y).fmod(p)
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.fmod(p1.order) if p1.order != nil
114
- return :infinity if e == GMP::Z.new(0)
115
- if e > GMP::Z.new(0)
116
- e3 = 3 * e
117
- negative_self = Point.new(p1.curve, p1.x, -p1.y, p1.order)
118
- i = Point.leftmost_bit(e3).tdiv(2)
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 > GMP::Z.new(1)
220
+ while gmp_cmp(i, 1) > 0
121
221
  result = Point.double(result)
122
- result = Point.add(result, p1) if (e3 & i) != GMP::Z.new(0) and (e & i) == GMP::Z.new(0)
123
- result = Point.add(result, negative_self) if (e3 & i) == GMP::Z.new(0) and (e & i) != GMP::Z.new(0)
124
- i = i.tdiv(2)
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 > GMP::Z.new(0)
132
- result = GMP::Z.new(1)
133
- while result <= x
134
- result *= 2
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.tdiv(2)
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 * p1.y).invert(p)
144
- three_x2 = 3 * (p1.x ** 2)
145
- l = ((three_x2 + a) * inverse).fmod(p)
146
- x3 = (l ** 2 - 2 * p1.x).fmod(p)
147
- y3 = (l * (p1.x - x3) - p1.y).fmod(p)
148
- y3 = p + y3 if 0 > y3
149
- p3 = Point.new(p1.curve, x3, y3)
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 = GMP::Z.new('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16)
174
- _r = GMP::Z.new('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16)
175
- _b = GMP::Z.new('0000000000000000000000000000000000000000000000000000000000000007', 16)
176
- _Gx = GMP::Z.new('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16)
177
- _Gy = GMP::Z.new('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16)
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 = GMP::Z.new(mpk[0, 64], 16)
183
- y = GMP::Z.new(mpk[64, 64], 16)
184
- z = GMP::Z.new(sha256(sha256_raw(idx.to_s + ':0:' + hex_to_bin(mpk))), 16)
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.to_s(16).rjust(64, '0') + pt.y.to_s(16).rjust(64, '0'))
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 = GMP::Z.new(addr, 16).to_s(58)
291
+ num = gmp_strval(gmp_init(addr, 16), 58)
193
292
  num = num.tr('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv', '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz')
194
293
 
195
294
  pad = ''
@@ -1,3 +1,3 @@
1
1
  module BitcoinAddrgen
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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.1
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-06-24 00:00:00.000000000 Z
12
+ date: 2013-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: gmp
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: 0.6.0
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: 0.6.0
29
+ version: 1.2.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rspec
32
32
  requirement: !ruby/object:Gem::Requirement