-
-
Save mwerner/635acb12cbc9b5569d5d to your computer and use it in GitHub Desktop.
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} |
have you solve the problem ?
@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.
@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?
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)`
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"))
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
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
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?