0
votes

I'm trying to implement a Perl function for creating SAS tokens. Doing all according to documentation (https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas) I always get error "Signature fields not well formed".

My testing resource is "https://ribdkstoragepoc.blob.core.windows.net/project-poc/foo/koteyka.jpg". Variables populated by my code:

signedpermissions = 'r'

signedexpiry = '2020-05-01T07:59:00Z'

canonicalizedresource = '/blob/ribdkstoragepoc/project-poc/foo/koteyka.jpg'

signedresource = 'b'

signedversion = '2018-03-28'

Other variables are just empty lines. I generate a string using the following pattern:

my $stringToSign = $permissions . "\n" . $start . "\n" . $expiry . "\n" . $canonicalizedResource . "\n" . $identifier . "\n" . $IP . "\n" . $protocol . "\n" . $version . "\n" . $resource . "\n" . $snapshotTime . "\n" . $rscc . "\n" . $rscd . "\n" . $rsce . "\n" . $rscl . "\n" . $rsct;

The string to sign:

r

2020-05-01T07:59:00Z
/blob/ribdkstoragepoc/project-poc/foo/koteyka.jpg



2018-03-28
b






Calculationg of signature: my $sig = Digest::SHA::hmac_sha256_base64($stringToSign, $key);

At last the final URL looks like: https://ribdkstoragepoc.blob.core.windows.net/project-poc/foo/koteyka.jpg?sig=YcwWvOT2FtOZGbXQxMAoSxvA2HhRmMAUp%2B6WUY%2Bjbjg&sv=2018-03-28&se=2020-05-01T07%3A59%3A00Z&sr=b&sp=r

As I have already said that does not work. Does anyone have ideas what could be wrong?

1
Can you edit your question and include the value of stringToSign?Gaurav Mantri
Thanks for updating. Your stringToSign looks ok to me. Can you try by changing the following code: $sig = Digest::SHA::hmac_sha256_base64($stringToSign, $key); to $sig = Digest::SHA::hmac_sha256_base64($stringToSign, decode_base64($key));?Gaurav Mantri
@GauravMantri That is already done: the $key is the result of decode_base64( $key_b64) );Infarch

1 Answers

1
votes

Figured out what's wrong with your code. Basically you're using 2018-03-28 version of Storage REST API so you don't need to include $resource and $snapshotTime in your $stringToSign.

Furthermore, you will need to pad your signature with 1-4 = (Ref: https://github.com/smarx/waz-storage-perl/blob/master/WindowsAzure/Storage.pm#L42).

Based on these, here's the code:

use strict;
use warnings;
use Digest::SHA qw(hmac_sha256_base64);
use MIME::Base64;

my $permissions = 'r';
my $start = '';
my $expiry = '2020-01-31T00:00:00Z';
my $canonicalizedResource = '/blob/ribdkstoragepoc/project-poc/foo/koteyka.jpg';
my $identifier = '';
#my $resource = 'b';
my $IP = '';
my $version = '2018-03-28';
my $protocol = '';
#my $snapshotTime = '';
my $rscc = '';
my $rscd = '';
my $rsce = '';
my $rscl = '';
my $rsct = '';

my $stringToSign = $permissions . "\n" . $start . "\n" . $expiry . "\n" . $canonicalizedResource . "\n" . $identifier . "\n" . $IP . "\n" . $protocol . "\n" . $version . "\n" . $rscc . "\n" . $rscd . "\n" . $rsce . "\n" . $rscl . "\n" . $rsct;

print $stringToSign;

my $accountKey = 'your-base64-account-key';

my $sig = Digest::SHA::hmac_sha256_base64($stringToSign, decode_base64($accountKey));
$sig .= '=' x (4 - (length($sig) % 4));
print "\n---------------------\n";

print $sig;

print "\n";

Give this a try, it should work.