Hexdigest() alternative in Squirrel?

Hi, guys!

I’m trying to compile a secure POST header for a service I’m integrating with, but I’ve hit a bump.

Here’s how it would look in Python:

sign = hmac.new(self.Secret, post_data, hashlib.sha512).hexdigest()

This would return a 256 character string ( http://forums.udacity.com/questions/100116165/what-does-hexdigest-and-what-does-it-do ).

I’m trying to accomplish the same in Squirrel like this:

`function BlobToHexString(data) {
//local str = “0x”;
local str;
foreach (b in data) {
if(!str)str = format("%02X", b);
else
str += format("%02X", b);
}
return str;
}

local sign = BlobToHexString(http.hash.hmacsha512(post_data, Secret));`

The BlobToHexString function was taken from the Imp docs ( https://electricimp.com/docs/api/http/hash/hmacsha512/ ) and slightly modified as to remove the 0x off the resulting string.

Problem is that I’m getting a 128 character long string, which means that hexdigest() and BlobToHexString() must be doing different things…

Anyone care to help?

Thanks in advance!

SHA512 produces a 512-bit result, which is 128 hex digits (each digit represents 4 bits) so a 128-character string. I think the Python result would also be a 128-character string here.

Peter

Hey,

Thanks for your note!

I don’t really know what the Python output would be, but the fact is that the POST is not accepted because of an error in this header, which could only be a result of my attempt to duplicate hexdigest().

Taken from the article quoted above ( http://forums.udacity.com/questions/100116165/what-does-hexdigest-and-what-does-it-do ):

Interesting to note, in order for the hexdigest string to fit in ascii, the hexdigest method produces a string twice the size of the hash in bytes, so in this case the hexdigest string is 32 bytes wide, not 16, the actual size of the hash in bytes. Each character is represented as an individual byte in ascii, just like any normal python string.

To compare:

len(hashlib.md5(‘test’).digest())
16

len(hashlib.md5(‘test’).hexdigest())
32
In summary hexdigest simply produces an ascii safe way to view the bytes produced from the hash algorithm.

As I understand, I should be ending up with a 256 char string?

Perhaps I’ve misunderstood the above?

The binary result of SHA-512, the digest(), is 512 bits or 64 bytes. The hexdigest() is twice that size, or 128 bytes.

Unfortunately, if it’s not working, you must either be hashing the wrong information or using the wrong secret. Even more unfortunately, the service won’t be all that helpful in telling you exactly what the problem was, as that could lead to security holes.

Peter

@peter is correct that you should end up with a 128 character string…

Here’s a quick python example:

import hashlib import hmac hashResult = hmac.new("secret", "data", hashlib.sha512).hexdigest() print hashResult.__len__() print hashResult

This results in:

128 6274071d33dec2728a2a1c903697fc1210b3252221c3d137e12d9f1ae5c8ed53e05e692b05a9eefff289667e2387c0fc0bd8a3d9bd7000782730c856a77a77d5

You’ve almost got it - but the loop in your BlobToHex function will occasionally return strings longer than 2 characters (padded with FF at the start)… here’s some code that should work for you:

`function BlobToHexString(data) {
local str = “”;
foreach (b in data) {
local c = format("%02x", b);
str += c.slice(c.len()-2);
}
return str;
}

function test() {
local secret = “secret”;
local data = “data”;

local hash = http.hash.hmacsha512(data, secret);

// from the python script..
local expected = "6274071d33dec2728a2a1c903697fc1210b3252221c3d137e12d9f1ae5c8ed53e05e692b05a9eefff289667e2387c0fc0bd8a3d9bd7000782730c856a77a77d5";
local actual = BlobToHexString(hash.tostring());

server.log(expected.tolower());
server.log(actual.tolower());

if (expected == actual) {
    server.log("Test Passed");
} else {
    server.log("Test Failed");
}

}

test();`

the loop in your BlobToHex function will occasionally return strings longer than 2 characters (padded with FF at the start)

If you can catch it doing that, it’s a bug and we’ll fix it… characters in Squirrel blobs and strings are meant to be unsigned (at least in Imp Squirrel – in upstream Squirrel they are signed on some platforms).

Peter

Neat - did not realize that!

Hey, guys!

Thanks for the help!

I ended up with the following alternative for hexdigest() based on your input:

function BlobToHexString(data) { local str = ""; foreach (b in data) { local c = format("%02x", b); str += c.slice(c.len()-2); } return str.tolower().tostring(); }

Sadly, I’m still not getting an OK from the service :frowning:

I’ll continue debugging and let you know once I get to the bottom of it.

Take care!

Hey, guys!

Finally got the request to go through - turns out that we were sending the correct data with the function above! Thanks for all of your help!

I did, however, hit kind of a strange issue, which I had to work around - I’m able to successfully decode the JSON the service is passing back, but they’re passing a nested table with a key called “return”.

And, naturally, I get an error in the IDE when I try to address it as

data.return

:frowning:

I just copied the pointer into another variable and addressed it from there, but I was wondering whether there was a more elegant way of addressing a nested table called “return” in Squirrel without this workaround.

Thanks in advance!

You could use data["return"]

:slight_smile: Thanks for the quick reply!

Knew I was close, but forgot to put in the quotation marks :slight_smile: