RejectedSoftware Forums

Sign up

HTTP request with header parameter and hmac sha512

Hi

I am really enjoying making web requests and doing async operations with vibe.d.

But now I need to make a web request given a description and PHP example(https://bittrex.com/home/api) :

For this version, we use a standard HMAC-SHA512 signing. >Append apikey and nonce to your request and calculate the >HMAC hash and include it under an apisign header. Note: the nonce is not respected right now but will be enforced later.

$apikey='xxx';
$apisecret='xxx';
$nonce=time();
$uri='https://bittrex.com/api/v1.1/market/getopenorders?>apikey='.$apikey.'&nonce='.$nonce;
$sign=hashhmac('sha512',$uri,$apisecret);<br>$ch = curlinit($uri);
curlsetopt($ch, CURLOPTHTTPHEADER, >array('apisign:'.$sign));
$execResult = curlexec($ch);<br>$obj = jsondecode($execResult);

In my imagination I convert the example above to vibe.d like:

 string apikey="xxx";
string apisecret="xxx";
string nonce = Clock.currTime().toString();
string url = "https://bittrex.com/api/v1.1/market/getopenorders?apikey=" ~ apikey ~ "&nonce=" ~ nonce;
                        
auto hmac = HMAC!SHA512(apisecret.representation);
hmac.put(url.representation);
auto generatedHmac = hmac.finish();
char[] generatedHmacStr = cast(char[])generatedHmac[0..generatedHmac.length];
Json data;
try
{
    requestHTTP(url.dup,
            (scope req) {
                    req.method = HTTPMethod.GET;
                    req.headers["apisign"] = generatedHmacStr.idup;
            },
            (scope res) {
                    data = parseJsonString(res.bodyReader.readAllUTF8());
                    writeln(data);	
            }
    );
}
catch ( std.json.JSONException e )
{
    writeln("Exception was caught while authorization");
}
                

My code is not working and I am getting an exception like :

"Error: Expected valid JSON token, got '<!DOCTYPE HT'."

I am suspicious about three things :

1 - If string nonce = Clock.currTime().toString(); correct or not
if not how should I set the time?

2 - If char[] generatedHmacStr = cast(char[])generatedHmac[0..generatedHmac.length]; step correct or not

3 - If req.headers["apisign"] = generatedHmacStr.idup; step correct or not.

If you guys have exprience setting ubyte data to request header can you please answer my questions?

Best Regards
Erdem

Re: HTTP request with header parameter and hmac sha512

On Fri, 03 Nov 2017 23:15:38 GMT, Erdemdem wrote:

Hi

I am really enjoying making web requests and doing async operations with vibe.d.

But now I need to make a web request given a description and PHP example(https://bittrex.com/home/api) :

For this version, we use a standard HMAC-SHA512 signing. >Append apikey and nonce to your request and calculate the >HMAC hash and include it under an apisign header. Note: the nonce is not respected right now but will be enforced later.

(...)

My code is not working and I am getting an exception like :

"Error: Expected valid JSON token, got '<!DOCTYPE HT'."

I am suspicious about three things :

1 - If string nonce = Clock.currTime().toString(); correct or not
if not how should I set the time?

Usually a nonce should be generated with a cryptographic RNG, such as vibe.crypto.cryptorand.systemRNG(), but to make the code equivalent with the PHP version it should be Clock.currTime(UTC()).toUnixTime.to!string. The question is what the API accepts here - decimal number, hex number, or an arbitrary string.

2 - If char[] generatedHmacStr = cast(char[])generatedHmac[0..generatedHmac.length]; step correct or not

The PHP version generates a hex string AFAICS. In this case, string generatedHmacStr = std.digest.toHexString(generatedHmac) should do the same thing.

3 - If req.headers["apisign"] = generatedHmacStr.idup; step correct or not.

In this particular case, a cast(string) could be used, because requestHTTP is guaranteed to not leak/escape the values that are passed to it. However, using .idup is generally the safe choice and will only have a performance impact in high-load scenarios.

I'd also check res.statusCode in the response handler, because it seems like the server sends back HTML instead of JSON in case of (certain?) errors. Maybe the response actually contains helpful information for further debugging.

Re: HTTP request with header parameter and hmac sha512

Thanks a lot I think the problem was with "nonce" as we indicated .

I am putting what worked for me for bittrex 1.1 api maybe it will be useful for someone else.

string apikey="xxx";
string apisecret="xxx";
string nonce =  Clock.currTime(UTC()).toUnixTime.to!string;
string url = "https://bittrex.com/api/v1.1/market/getopenorders?apikey=" ~  
                        apikey ~ "&nonce=" ~ nonce;
                        
auto hmac = HMAC!SHA512(apisecret.representation);
hmac.put(url.representation);
auto generatedHmac = hmac.finish();
string generatedHmacStr = std.digest.digest.toHexString(generatedHmac);
Json data;	
try
{
    requestHTTP(url.dup,
            (scope req) {
                    req.method = HTTPMethod.GET;
                    req.headers["apisign"] = generatedHmacStr;
            },
            (scope res) {
                    data = parseJsonString(res.bodyReader.readAllUTF8());
                    writeln(data);	
            }
    );
}
catch ( std.json.JSONException e )
{
        writeln("Exception was caught while authorization", e);
}

I am using vibe.d extensively last 2 weeks. I have some interesting non-blocking findings I will post them very soon.

Best Regards
Erdem