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.
@@ -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