Franco Pettigrosso Franco Pettigrosso - 1 year ago 121
Node.js Question

trying to make hmac-sha256 work with powershell for Canvas API

I was appointed the task of making a process in which a PowerShell script needs to make a call to Canvas servers in order to get data out of it for other uses that are outside the scope of this question. The first thing I did was research how the Canvas API actually works. I eventually found this post holds everything I think I should know about the API. The API requires an HMAC SHA 256 hash. I have decided to reverse engineer his the writer's code that makes the hash in order to make the same script in PowerShell.

Here is my slightly edited code (node.js)

var crypto = require('crypto')
var url = require('url')
var HMAC_ALG = 'sha256'
var apiAuth = module.exports = {
buildMessage: function(secret, timestamp, uri) {
var urlInfo = url.parse(uri, false);
var query = urlInfo.query ? urlInfo.query.split('&').sort().join('&') : '';
var parts = [ 'GET',, '', '', urlInfo.pathname, query, timestamp, secret ]
return parts.join('\n');

buildHmacSig: function(secret, timestamp, reqOpts,message) {
//var message = apiAuth.buildMessage(secret, timestamp, reqOpts);
var hmac = crypto.createHmac(HMAC_ALG, new Buffer(secret))
return hmac.digest('base64')

Here are the parameters that I put in the node js application

var canvas = require('[filepath]/new_canvas');
var secret = 'mycrazysecret';
var today = new Date();
var timestamp= today.toUTCString();
var regOpts = 'mycrazymessage';
var message = canvas.buildMessage(secret, timestamp, regOpts)
var hmac = canvas.buildHmacSig(secret, timestamp, regOpts,message);

the final code it this

Here is my PowerShell file:

function buffer
param ($string)
Foreach ($element in $string.toCharArray()) {$c+= [System.Convert]::ToSByte($element)}
return $c

$message = 'GET\n\n\n\nmycrazymessage\n\nFri, 18 Nov 2016 15:29:52 GMT\nmycrazysecret'
$secret = 'mycrazysecret'
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = buffer -string $secret
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)

echo $signature

The final result is 'pF92zam81wclnnb8csDsscsSYNQ7it9qLrcJkRTi5rM='

I do not know getting the to produce the same results is even possible, but the question I am asking why aren't they producing to different results? (the keys are the same as well)

Answer Source

In PowerShell, the default escape sequence uses backticks ` rather than backslash \.

In order for the parser to recognize the escape sequence as not just a backtick character literal and the letter n, use an expandable string (" instead of '):

$message = "GET`n`n`n`nmycrazymessage`n`nFri, 18 Nov 2016 15:29:52 GMT`nmycrazysecret"

Other than that, your HMAC signature procedure is correct (it correctly outputs Oexq8/ulAGxSIQXGDVqoXyqk5x+n9cMrc3avcTW9aZk= after changing the $message value)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download