ci_block_io 1.7.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2abd2718e9c87fb33dc7aaecc59c39b475fd2d99c04738fb1f9334bd3e40c861
4
- data.tar.gz: 47a1b5f23851a355378cd89f50e07ef2090585d60653037bee1fbcdf78619ddf
3
+ metadata.gz: 93926bfd4df14d9634d0ea789c86fdd7737e485f129a7b966b52ea110ab96d46
4
+ data.tar.gz: b605c6dc58f4f2eb583691767f1ee2a7c97b8a920675787e4fcc6b46785d5480
5
5
  SHA512:
6
- metadata.gz: ce7c50a375b4ec74ca6ff03714b23fe7cde4a30fb29739f392ecb8423345b989be3f08c7fc3cf552ed4bcb6269098b2b25f617e839b6504ef7d3bb98a8087174
7
- data.tar.gz: e764bb64d1b075e8df6f6a360e952b82d0cb58786a05e6bfe4660e57e080d8c3cae15264a2b5b32914c618a43d82451d7a332170d9f3e249f3790281809394ef
6
+ metadata.gz: a492c73929e34c787b4cb7d4773f3024a0ffbbf0984a49bbccbf3e9c6739697ff70ea1cd04fe6cc39e419c45e2cc56d02c650dc076898cda9ed8187192caa03b
7
+ data.tar.gz: 26e60257ab22e318649b2f741807b591e73e41c4ce377ab6802f83510777f4a92e41bd5af9354e7f61c295b052f188b3279bba309b18685294ea8c9e545dfddd
data/lib/ci_block_io.rb CHANGED
@@ -30,18 +30,18 @@ module CiBlockIo
30
30
  # initialize BlockIo
31
31
  @api_key = args[:api_key]
32
32
  @pin = args[:pin]
33
-
33
+
34
34
  @encryptionKey = Helper.pinToAesKey(@pin) if !@pin.nil?
35
35
 
36
36
  hostname = args[:hostname] || "block.io"
37
37
  @base_url = "https://" << hostname << "/api/VERSION/API_CALL/?api_key="
38
-
38
+
39
39
  @client = HTTPClient.new
40
40
  @client.tcp_keepalive = true
41
41
  @client.ssl_config.ssl_version = :auto
42
-
42
+
43
43
  @version = args[:version] || 2 # default version is 2
44
-
44
+
45
45
  self.api_call(['get_balance',""])
46
46
  end
47
47
 
@@ -59,7 +59,7 @@ module CiBlockIo
59
59
  params = get_params(args.first)
60
60
  self.api_call([method_name, params])
61
61
  end
62
-
62
+
63
63
  end
64
64
 
65
65
  def self.withdraw(args = {}, method_name = 'withdraw')
@@ -72,7 +72,7 @@ module CiBlockIo
72
72
  params << "&pin=" << @pin if @version == 1 # Block.io handles the Secret PIN in the legacy API (v1)
73
73
 
74
74
  response = self.api_call([method_name, params])
75
-
75
+
76
76
  if response['data'].has_key?('reference_id') then
77
77
  # Block.io's asking us to provide some client-side signatures, let's get to it
78
78
 
@@ -114,7 +114,7 @@ module CiBlockIo
114
114
  params = get_params(args)
115
115
 
116
116
  response = self.api_call([method_name, params])
117
-
117
+
118
118
  if response['data'].has_key?('reference_id') then
119
119
  # Block.io's asking us to provide some client-side signatures, let's get to it
120
120
 
@@ -136,7 +136,7 @@ module CiBlockIo
136
136
 
137
137
 
138
138
  private
139
-
139
+
140
140
  def self.api_call(endpoint)
141
141
  return @mock_response[endpoint[0]] if @mock_response.keys.include?(endpoint[0])
142
142
 
@@ -145,21 +145,19 @@ module CiBlockIo
145
145
  return nil if base_url.nil? || @api_key.nil?
146
146
 
147
147
  response = @client.post(base_url + @api_key, endpoint[1])
148
-
148
+
149
149
  begin
150
150
  body = Oj.load(response.body)
151
151
  return unless body['status'].eql?('success')
152
152
  case endpoint[0]
153
- when 'withdraw' then
153
+ when 'withdraw'
154
154
  raise CiBlockIoWithdrawException.new(body['data']['error_message'])
155
155
  else
156
156
  raise Exception.new(body['data']['error_message'])
157
157
  end
158
- end
159
158
  rescue
160
159
  raise Exception.new('Unknown error occurred. Please report this.')
161
160
  end
162
-
163
161
  body
164
162
  end
165
163
 
@@ -169,7 +167,7 @@ module CiBlockIo
169
167
  # construct the parameter string
170
168
  params = ""
171
169
  args = {} if args.nil?
172
-
170
+
173
171
  args.each do |k,v|
174
172
  params += '&' if params.length > 0
175
173
  params += "#{k.to_s}=#{v.to_s}"
@@ -191,23 +189,23 @@ module CiBlockIo
191
189
  @compressed = compressed
192
190
 
193
191
  end
194
-
192
+
195
193
  def private_key
196
194
  # returns private key in hex form
197
195
  return @private_key.to_s(16)
198
196
  end
199
-
197
+
200
198
  def public_key
201
199
  # returns the compressed form of the public key to save network fees (shorter scripts)
202
200
 
203
201
  return ECDSA::Format::PointOctetString.encode(@public_key, compression: @compressed).unpack("H*")[0]
204
202
  end
205
-
203
+
206
204
  def sign(data)
207
205
  # signed the given hexadecimal string
208
206
 
209
207
  nonce = deterministicGenerateK([data].pack("H*"), @private_key) # RFC6979
210
-
208
+
211
209
  signature = ECDSA.sign(@group, @private_key, data.to_i(16), nonce)
212
210
 
213
211
  # BIP0062 -- use lower S values only
@@ -221,14 +219,14 @@ module CiBlockIo
221
219
  # DER encode this, and return it in hex form
222
220
  return ECDSA::Format::SignatureDerString.encode(signature).unpack("H*")[0]
223
221
  end
224
-
222
+
225
223
  def self.from_passphrase(passphrase)
226
224
  # create a private+public key pair from a given passphrase
227
225
  # think of this as your brain wallet. be very sure to use a sufficiently long passphrase
228
226
  # if you don't want a passphrase, just use Key.new and it will generate a random key for you
229
-
227
+
230
228
  raise Exception.new('Must provide passphrase at least 8 characters long.') if passphrase.nil? or passphrase.length < 8
231
-
229
+
232
230
  hashed_key = Helper.sha256([passphrase].pack("H*")) # must pass bytes to sha256
233
231
 
234
232
  return Key.new(hashed_key)
@@ -246,65 +244,65 @@ module CiBlockIo
246
244
  return Key.new(actual_key, compressed)
247
245
 
248
246
  end
249
-
247
+
250
248
  def isPositive(i)
251
249
  sig = "!+-"[i <=> 0]
252
-
250
+
253
251
  return sig.eql?("+")
254
252
  end
255
-
253
+
256
254
  def deterministicGenerateK(data, privkey, group = ECDSA::Group::Secp256k1)
257
255
  # returns a deterministic K -- RFC6979
258
256
 
259
257
  hash = data.bytes.to_a
260
258
 
261
259
  x = [privkey.to_s(16)].pack("H*").bytes.to_a
262
-
260
+
263
261
  k = []
264
262
  32.times { k.insert(0, 0) }
265
-
263
+
266
264
  v = []
267
265
  32.times { v.insert(0, 1) }
268
-
266
+
269
267
  # step D
270
268
  k = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), [].concat(v).concat([0]).concat(x).concat(hash).pack("C*")).bytes.to_a
271
-
269
+
272
270
  # step E
273
271
  v = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), v.pack("C*")).bytes.to_a
274
-
272
+
275
273
  # puts "E: " + v.pack("C*").unpack("H*")[0]
276
-
274
+
277
275
  # step F
278
276
  k = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), [].concat(v).concat([1]).concat(x).concat(hash).pack("C*")).bytes.to_a
279
-
277
+
280
278
  # step G
281
279
  v = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), v.pack("C*")).bytes.to_a
282
-
280
+
283
281
  # step H2b (Step H1/H2a ignored)
284
282
  v = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), v.pack("C*")).bytes.to_a
285
-
283
+
286
284
  h2b = v.pack("C*").unpack("H*")[0]
287
285
  tNum = h2b.to_i(16)
288
-
286
+
289
287
  # step H3
290
288
  while (!isPositive(tNum) or tNum >= group.order) do
291
289
  # k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0])]), k)
292
290
  k = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), [].concat(v).concat([0]).pack("C*")).bytes.to_a
293
-
291
+
294
292
  # v = crypto.HmacSHA256(v, k)
295
293
  v = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), k.pack("C*"), v.pack("C*")).bytes.to_a
296
-
294
+
297
295
  # T = BigInteger.fromBuffer(v)
298
296
  tNum = v.pack("C*").unpack("H*")[0].to_i(16)
299
297
  end
300
-
298
+
301
299
  return tNum
302
300
  end
303
301
 
304
302
  end
305
-
303
+
306
304
  module Helper
307
-
305
+
308
306
  def self.signData(inputs, keys)
309
307
  # sign the given data with the given keys
310
308
  # TODO loop is O(n^3), make it better
@@ -320,7 +318,7 @@ module CiBlockIo
320
318
  while j < input['signers'].size do
321
319
  # if our public key matches this signer's public key, sign the data
322
320
  signer = inputs[i]['signers'][j]
323
-
321
+
324
322
  k = 0
325
323
  while k < keys.size do
326
324
  # sign for each key provided, if we can
@@ -342,19 +340,19 @@ module CiBlockIo
342
340
  # passphrase is in plain text
343
341
  # encrypted_data is in base64, as it was stored on Block.io
344
342
  # returns the private key extracted from the given encrypted data
345
-
343
+
346
344
  decrypted = self.decrypt(encrypted_data, b64_enc_key)
347
-
345
+
348
346
  return Key.from_passphrase(decrypted)
349
347
  end
350
-
348
+
351
349
  def self.sha256(value)
352
350
  # returns the hex of the hash of the given value
353
351
  hash = Digest::SHA2.new(256)
354
352
  hash << value
355
353
  hash.hexdigest # return hex
356
354
  end
357
-
355
+
358
356
  def self.pinToAesKey(secret_pin, iterations = 2048)
359
357
  # converts the pincode string to PBKDF2
360
358
  # returns a base64 version of PBKDF2 pincode
@@ -366,10 +364,10 @@ module CiBlockIo
366
364
 
367
365
  return Base64.strict_encode64(aes_key_bin) # the base64 encryption key
368
366
  end
369
-
367
+
370
368
  # Decrypts a block of data (encrypted_data) given an encryption key
371
369
  def self.decrypt(encrypted_data, b64_enc_key, iv = nil, cipher_type = 'AES-256-ECB')
372
-
370
+
373
371
  response = nil
374
372
 
375
373
  begin
@@ -385,7 +383,7 @@ module CiBlockIo
385
383
 
386
384
  return response
387
385
  end
388
-
386
+
389
387
  # Encrypts a block of data given an encryption key
390
388
  def self.encrypt(data, b64_enc_key, iv = nil, cipher_type = 'AES-256-ECB')
391
389
  aes = OpenSSL::Cipher.new(cipher_type)
@@ -396,7 +394,7 @@ module CiBlockIo
396
394
  end
397
395
 
398
396
  # courtesy bitcoin-ruby
399
-
397
+
400
398
  def self.int_to_base58(int_val, leading_zero_bytes=0)
401
399
  alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
402
400
  base58_val, base = '', alpha.size
@@ -406,7 +404,7 @@ module CiBlockIo
406
404
  end
407
405
  base58_val
408
406
  end
409
-
407
+
410
408
  def self.base58_to_int(base58_val)
411
409
  alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
412
410
  int_val, base = 0, alpha.size
@@ -416,12 +414,12 @@ module CiBlockIo
416
414
  end
417
415
  int_val
418
416
  end
419
-
417
+
420
418
  def self.encode_base58(hex)
421
419
  leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
422
420
  ("1"*leading_zero_bytes) + Helper.int_to_base58( hex.to_i(16) )
423
421
  end
424
-
422
+
425
423
  def self.decode_base58(base58_val)
426
424
  s = Helper.base58_to_int(base58_val).to_s(16); s = (s.bytesize.odd? ? '0'+s : s)
427
425
  s = '' if s == '00'
@@ -430,5 +428,4 @@ module CiBlockIo
430
428
  s
431
429
  end
432
430
  end
433
-
434
431
  end
@@ -1,3 +1,3 @@
1
1
  module CiBlockIo
2
- VERSION = "1.7.0"
2
+ VERSION = "1.7.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ci_block_io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Atsuhiro Tsuruta feat. Atif Nazir