For querrying a REST API I need to authenticate with HMAC-SHA256. Does anybody know of a way to do this in JSL? We might even use another REST API or webscraper to do it. For example this website: https://www.devglan.com/online-tools/hmac-sha256-online can calculate the hash but how do I make it work?
@Craige_Hales for some reason I got it to work earlier today, then saved it and now it won't work anymore. Can you see my mistake? BITS.jsl and AUTH.jsl from your twitterpackage are also attached for reference.
Update, it was the blocksize, it is 64 for SHA265 I had assumed that is should be 265
include("BITS.jsl");
SHA256 = Function( {txt},
{hash, rc, hexdata,temppath},
try(deleteFile("$temp/deleteme.txt"));
temppath = Save Text File( "$temp/deleteme.txt", txt );
If( Host is( "windows" ),
hash = RunProgram( executable( "certutil" ), options( "-hashfile "|| temppath|| " SHA256" ), readfunction( "text" ) ); // win jmp 11
//hash = RunProgram( executable( "certutil" ), options( {"-hashfile", temppath, "SHA1"} ), readfunction( "text" ) );
rc = Pat Match(
hash,
Pat Regex( "\[^.+?:\s+]\" ) + Pat Span( "0123456789abcdefABCDEF " ) >> hexdata + Pat Regex(
"\[\s*CertUtil: -hashfile command completed successfully.\s*$]\"
)
);
If( rc != 1,
Throw( "bad hash:" || hash )
);
hexdata = Regex( hexdata, " ", "", GLOBALREPLACE );
, // else MAC
hash = RunProgram( executable( "/usr/bin/openssl" ), options( {"dgst", "-sha1", temppath} ), readfunction( "text" ) );
hexdata =regex(hash,"=\s*([0-9a-fA-F]{40})\s*","\1");
if( length(hexdata) != 40, throw("bad hash:" || hash));
);
try(deleteFile("$temp/deleteme.txt"),show("did not delete temp file??"));
Return( Hex To Blob( hexdata ) );
);
HMACSHA256 = Function( {key, message},
{blocksize = 64}, // Where blocksize is that of the underlying hash function
//show(length(key));
If(
Length( key ) > blocksize, // keys longer than blocksize are shortened
//print("shorten:");
key = SHA256( key );
//show(key,length(key));
);
if(
Length( key ) < blocksize, // keys shorter than blocksize are zero-padded
key = key || Matrix To Blob( J( (blocksize - Length( key )), 1, 0 ), "uint", 1, "big" )
);
//show(length(key));
o_key_pad = BITS:XORBLOB( Matrix To Blob( J( blocksize, 1, Hex To Number( "5c" ) ), "uint", 1, "big" ), key );
i_key_pad = BITS:XORBLOB( Matrix To Blob( J( blocksize, 1, Hex To Number( "36" ) ), "uint", 1, "big" ), key );
Return( SHA256( o_key_pad || SHA256( i_key_pad || message ) ) );
);
//from https://www.devglan.com/online-tools/hmac-sha256-online
if("090a613de1a32c513f5477019dbd395fe4c6727708e945277d6af6c5cf7a6778" != hex(HMACSHA256( Char To Blob( "dbc62ec300b2624c580611858d94f2332ac63" ), Char To Blob( "Why don't we test this" ) )), throw("hmac busted"));I checked the certutil SHA256 function and that generates correct hashes. It seems that the HMACSHA256 or in the BITS functions that it calls, where it goes wrong.
certutil on windows. openssl on mac. (But I think you might not need to, see final sentence below.)
A long time ago in 7 things to know about Twitter I needed a SHA1. "certutil" is already installed on windows and will apparently do SHA256 as well. You might start with the code in the .zip AUTH.jsl file which uses runprogram and parses the output.
You'll get a bunch of choices of varying quality with this search https://www.google.com/search?q=windows+hmac+sha256+certutil
The HMAC part is described https://en.wikipedia.org/wiki/HMAC and there appears to be a related function in the AUTH.jsl file. It's been a long time since I thought about it.
I think this may be built in to JMP's httpRequest/oauth2 functions as well @Paul_Nelson @bryan_boone but I've not studied them yet.
try uppercase() on the left-hand-side test value. Looks like it works.
HMAC-SHA256 is not currently built in to HTTP Request/OAuth2.
It would have to be done the way Craige described.