Skip to content

Instantly share code, notes, and snippets.

@mwerner
Last active July 18, 2018 12:13
Show Gist options
  • Save mwerner/635acb12cbc9b5569d5d to your computer and use it in GitHub Desktop.
Save mwerner/635acb12cbc9b5569d5d to your computer and use it in GitHub Desktop.
Invalid Bittrex Signature
require 'faraday'
require 'base64'
require 'cgi'
host = 'https://bittrex.com/api/v1.1'
key = '5231569363514ee5a5a598efb483c25c'
secret = '54e4a7e2a34f4d3bb9a93f765e47cf69'
path = '/account/getorderhistory'
nonce = Time.now.to_i
url = "#{host}#{path}?apikey=#{key}&nonce=#{nonce}"
connection = Faraday.new(:url => host) do |faraday|
faraday.request :url_encoded
faraday.adapter Faraday.default_adapter
end
puts "\n1: full url+queryparams, with specified params, url/secret in signature"
response = connection.get do |req|
puts "URL: #{url}"
req.url(url)
req.params[:apikey] = key
req.params[:nonce] = nonce
puts req.params.inspect
digest = OpenSSL::HMAC.hexdigest('sha512', url, secret)
signature = CGI.escape(Base64.encode64("#{digest}\n")).chomp
puts "Signed: #{signature}"
req.headers[:apisign] = signature
end
puts response.body
puts
puts "\n2: path, specified params, full url/secret in signature"
response = connection.get do |req|
puts "URL: #{path}"
req.url(path)
req.params[:apikey] = key
req.params[:nonce] = nonce
puts req.params.inspect
digest = OpenSSL::HMAC.hexdigest('sha512', url, secret)
signature = CGI.escape(Base64.encode64("#{digest}\n")).chomp
puts "Signed: #{signature}"
req.headers[:apisign] = signature
end
puts response.status
puts "\n3: path, specified params, path/secret in signature"
response = connection.get do |req|
puts "URL: #{path}"
req.url(path)
req.params[:apikey] = key
req.params[:nonce] = nonce
puts req.params.inspect
digest = OpenSSL::HMAC.hexdigest('sha512', path, secret)
signature = CGI.escape(Base64.encode64("#{digest}\n")).chomp
puts "Signed: #{signature}"
req.headers[:apisign] = signature
end
puts response.status
puts "\n4: full url requested, with no params specified, path/secret in signature"
response = connection.get do |req|
puts "URL: #{url}"
req.url(url)
puts req.params.inspect
digest = OpenSSL::HMAC.hexdigest('sha512', path, secret)
signature = CGI.escape(Base64.encode64("#{digest}\n")).chomp
puts "Signed: #{signature}"
req.headers[:apisign] = signature
end
puts response.body
puts "\n5: url with no params, params specified, host/path/secret in signature"
response = connection.get do |req|
puts "URL: #{host}/#{path}"
req.url("#{host}/#{path}")
req.params[:apikey] = key
req.params[:nonce] = nonce
puts req.params.inspect
digest = OpenSSL::HMAC.hexdigest('sha512', "#{host}/#{path}", secret)
signature = CGI.escape(Base64.encode64("#{digest}\n")).chomp
puts "Signed: #{signature}"
req.headers[:apisign] = signature
end
puts response.body
puts "\n6: url with no params, params specified, url/secret in signature"
response = connection.get do |req|
puts "URL: #{host}/#{path}"
req.url("#{host}/#{path}")
req.params[:apikey] = key
req.params[:nonce] = nonce
puts req.params.inspect
digest = OpenSSL::HMAC.hexdigest('sha512', url, secret)
signature = CGI.escape(Base64.encode64("#{digest}\n")).chomp
puts "Signed: #{signature}"
req.headers[:apisign] = signature
end
puts response.body
# Results
# $> ruby ~/Desktop/bittrex.rb
# 1: full url+queryparams, with specified params, url/secret in signature
# URL: https://bittrex.com/api/v1.1/account/getorderhistory?apikey=5231569363514ee....98efb483c25c&nonce=1403655423
# {"apikey"=>"5231569363514ee....98efb483c25c", "nonce"=>1403655423}
# Signed: MDMzMjI1M2RkNjY3NTA4YjU0ZjUwMjIwM2MxYzkxYWNhYzQxZGRhMTE0Yzdh%0AOGFkMThlOTYyZTBjNmVmZWE1ZTFiMWQ2MGRkMGZmZmVhMzRjNjc3N2NhNDNl%0AZjE3YjljYzczODRjYTljOGI3MTM3ODc2OWU5ODdjZTkyNWYzZmYK%0A
# {"success":false,"message":"INVALID_SIGNATURE","result":null}
# 2: path, specified params, full url/secret in signature
# URL: /account/getorderhistory
# {"apikey"=>"5231569363514ee....98efb483c25c", "nonce"=>1403655423}
# Signed: MDMzMjI1M2RkNjY3NTA4YjU0ZjUwMjIwM2MxYzkxYWNhYzQxZGRhMTE0Yzdh%0AOGFkMThlOTYyZTBjNmVmZWE1ZTFiMWQ2MGRkMGZmZmVhMzRjNjc3N2NhNDNl%0AZjE3YjljYzczODRjYTljOGI3MTM3ODc2OWU5ODdjZTkyNWYzZmYK%0A
# 404
# 3: path, specified params, path/secret in signature
# URL: /account/getorderhistory
# {"apikey"=>"5231569363514ee....98efb483c25c", "nonce"=>1403655423}
# Signed: YjYwMTNjMTkwYjQxYzMwNjhjZmU5NjQyYjVkYmI0ZDk1MmY4NmQzNTg4ZGM1%0ANjFjZGQzYmEwYjVlZDBiMjhmOTMzZjhiODcyOGEyMjM5YWVmOGYxZjQ3ZGZl%0AOTc3NGUzYzVhYzhmMzAwYTBhNzkxYzZhNTQ1Y2U4Y2ZmYmI4MWEK%0A
# 404
# 4: full url requested, with no params specified, path/secret in signature
# URL: https://bittrex.com/api/v1.1/account/getorderhistory?apikey=5231569363514ee....98efb483c25c&nonce=1403655423
# {"apikey"=>"5231569363514ee....98efb483c25c", "nonce"=>"1403655423"}
# Signed: YjYwMTNjMTkwYjQxYzMwNjhjZmU5NjQyYjVkYmI0ZDk1MmY4NmQzNTg4ZGM1%0ANjFjZGQzYmEwYjVlZDBiMjhmOTMzZjhiODcyOGEyMjM5YWVmOGYxZjQ3ZGZl%0AOTc3NGUzYzVhYzhmMzAwYTBhNzkxYzZhNTQ1Y2U4Y2ZmYmI4MWEK%0A
# {"success":false,"message":"INVALID_SIGNATURE","result":null}
# 5: url with no params, params specified, host/path/secret in signature
# URL: https://bittrex.com/api/v1.1//account/getorderhistory
# {"apikey"=>"5231569363514ee....98efb483c25c", "nonce"=>1403655423}
# Signed: ODA3MGU2NmU5MjIxYjdjMWQ3ZDVmY2VjNTJjOGU5ZDg1MWZhOWM2Zjc3MDE5%0ANTcwYTMwZjQxZjgyMTdiMGFiMmNlM2M4YmQzMWJhMDBjMmYxMGMwNTNkMWZk%0ANjMwNjE2ZjE2N2E3MzYyOTdjZTRmMTk4MWIwY2FiZjdmZmEzMDgK%0A
# {"success":false,"message":"INVALID_SIGNATURE","result":null}
# 6: url with no params, params specified, url/secret in signature
# URL: https://bittrex.com/api/v1.1//account/getorderhistory
# {"apikey"=>"5231569363514ee....98efb483c25c", "nonce"=>1403655423}
# Signed: MDMzMjI1M2RkNjY3NTA4YjU0ZjUwMjIwM2MxYzkxYWNhYzQxZGRhMTE0Yzdh%0AOGFkMThlOTYyZTBjNmVmZWE1ZTFiMWQ2MGRkMGZmZmVhMzRjNjc3N2NhNDNl%0AZjE3YjljYzczODRjYTljOGI3MTM3ODc2OWU5ODdjZTkyNWYzZmYK%0A
# {"success":false,"message":"INVALID_SIGNATURE","result":null}
@kayagoban
Copy link

kayagoban commented Nov 27, 2016

I've had similar problems getting the HMAC signature to take for Bittrex API calls, using ruby and faraday. Did you ever find a solution?

@Resory
Copy link

Resory commented Jun 16, 2017

have you solve the problem ?

@bermann
Copy link

bermann commented Jun 18, 2017

@Resory I just solved it, the problem is that you have to generate the hash with the exact same url (including parameters) as the call.

@Resory
Copy link

Resory commented Jun 21, 2017

@bermann i did generate the hash with the exact same url , the fact is , i use object-c for coding, and i use object-c generate the hash string , then i record the hash string , and run the bittrex demo with same url , then get the same hash string ... but still get the " "INVALID_SIGNATURE", please help me solve the problem T_T... is it bittrex don't support iOS request?

@bermann
Copy link

bermann commented Jun 23, 2017

@Resory check this gist. That's how I made it work in ruby

@zerbra
Copy link

zerbra commented Jun 28, 2017

Hi, I am making an application in autoit for Bittrex API, and have successfully encrypted the apisign with the URL and the api key & secret with HMAC SHA 512. It worked quite well on Poloniex API but for the Bittrex API, the response still return as Invalid. Looks like there are some string that need to be encoded. Can you give me some kind of short explanation over this? Many thanks man!

My code is like:

`
Func hmac($key, $message, $algo)
Local $blocksize = 128
Local $a_opad[$blocksize], $a_ipad[$blocksize]
Local Const $oconst = 0x5C, $iconst = 0x36
Local $opad = Binary(''), $ipad = Binary('')
$key = Binary($key)
If BinaryLen($key) > $blocksize Then $key = _HASH($key, $algo)
For $i = 1 To BinaryLen($key)
$a_ipad[$i-1] = Number(BinaryMid($key, $i, 1))
$a_opad[$i-1] = Number(BinaryMid($key, $i, 1))
Next
For $i = 0 To $blocksize - 1
$a_opad[$i] = BitXOR($a_opad[$i], $oconst)
$a_ipad[$i] = BitXOR($a_ipad[$i], $iconst)
Next
For $i = 0 To $blocksize - 1
$ipad &= Binary('0x' & Hex($a_ipad[$i],2))
$opad &= Binary('0x' & Hex($a_opad[$i],2))
Next
;Return Call($algo, $opad & Call($algo, $ipad & Binary($message)))
Local $ret = _HASH($ipad & Binary($message), $algo)
$ret = _HASH($opad & $ret, $algo)
Return $ret
ConsoleWrite("time is (in hmac)"&$time& @crlf)
Return StringLower(hex(hmac($key,$message, "SHA_512")))
EndFunc

$api_key='xxx'

$command = ""
$command2= ""

Func HttpGet($sURL, $sData = "")
Local $secret='xxx'
$api_key='xxx'
ConsoleWrite("time is (in GET) "&$time& @crlf)
$sign =StringLower(hex(hmac($secret,$command,"SHA_512")))

Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1")

$oHTTP.Open("GET", $sURL & "?" & $sData, False)
If (@error) Then Return SetError(1, 0, 0)
$oHTTP.SetRequestHeader("Content-Type","application/x-www-form-urlencoded")
$oHTTP.SetRequestHeader('apisign',$sign)

$oHTTP.Send($sData)
If (@error) Then Return SetError(2, 0, 0)

If ($oHTTP.Status <> $HTTP_STATUS_OK) Then Return SetError(3, 0, 0)

Return SetError(0, 0, $oHTTP.ResponseText)
EndFunc

$command="https://bittrex.com/api/v1.1/market/getopenorders?apikey=xxx&nonce="&$time

Global $return = HttpGet($command)
ConsoleWrite($return&@crlf)`

@mr-morkou
Copy link

mr-morkou commented Jul 9, 2017

Solve
get https://bittrex.com/api/v1.1/market/buylimit?apikey=LALA&market=BTC-LTC&quantity=0.4&rate=0.018&nonce=1499617500
nonce to the end
HMAC full url
OpenSSL::HMAC.hexdigest('sha512', secret.encode("ASCII"), FULLURL.encode("ASCII"))

@mr-morkou
Copy link

mr-morkou commented Jul 9, 2017

and + faraday.options.params_encoder = DoNotEncoder

  def connection
      @connection ||= Faraday.new(:url => HOST) do |faraday|
        faraday.request  :url_encoded
        faraday.adapter  Faraday.default_adapter
        # faraday.response :logger
        faraday.options.params_encoder = DoNotEncoder
      end
    end
class DoNotEncoder
      def self.encode(params)
        buffer = ''
        params.each do |key, value|
          buffer << "#{key}=#{value}&"
        end
      return buffer.chop
      end
  end

@tarun1475
Copy link

Look at this function it is working fine for me and tested.

function calculateSign(url){
var sign=crypto.createHmac('sha512',constants.bittrexCredentials.SECRET);

sign = sign.update(url,'ascii');
sign = sign.digest('hex');
return sign;

}
Full Implementation repo : https://github.com/tarun1475/Nodejs-Bittrex-Client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment