ci_block_io 1.7.0 → 1.7.1
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.
- checksums.yaml +4 -4
- data/lib/ci_block_io.rb +48 -51
- data/lib/ci_block_io/version.rb +1 -1
- metadata +1 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 93926bfd4df14d9634d0ea789c86fdd7737e485f129a7b966b52ea110ab96d46
         | 
| 4 | 
            +
              data.tar.gz: b605c6dc58f4f2eb583691767f1ee2a7c97b8a920675787e4fcc6b46785d5480
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 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' | 
| 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
         | 
    
        data/lib/ci_block_io/version.rb
    CHANGED