Skip to content

Instantly share code, notes, and snippets.

@mwerner
Last active July 18, 2018 12:13
Show Gist options
  • Select an option

  • Save mwerner/635acb12cbc9b5569d5d to your computer and use it in GitHub Desktop.

Select an option

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

kayagoban commented Nov 27, 2016

Copy link
Copy Markdown

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

Resory commented Jun 16, 2017

Copy link
Copy Markdown

have you solve the problem ?

@bermann

bermann commented Jun 18, 2017

Copy link
Copy Markdown

@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

Resory commented Jun 21, 2017

Copy link
Copy Markdown

@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

bermann commented Jun 23, 2017

Copy link
Copy Markdown

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

@zerbra

zerbra commented Jun 28, 2017

Copy link
Copy Markdown

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

mr-morkou commented Jul 9, 2017

Copy link
Copy Markdown

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

mr-morkou commented Jul 9, 2017

Copy link
Copy Markdown

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
Copy Markdown

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