0
votes

I'm having some problems generating SAS token to download the file of Azure Storage. The following produces a URI that does not work. The error message I get back is Signature did not match, and I'm uncertain why.

Has anyone generated SAS tokens, and got the signature to match manually?

    static void Main(string[] args)
    {
        var sas = generateSAS
        (
            key,            // Azure portal very secret ^-^
            keyName,        // Azure portal, example: key1
            resourceUri,    // example: https://myaccount.blob.core.windows.net/emails/email.pdf
            resourcePath    // example: /blob/myaccount/emails/email.pdf
        );
    }

    private static string generateSAS(string key, string keyName, string uri, string path)
    {
        var permissions = "r";
        var startTime = DateTime.UtcNow;
        var endTime = DateTime.UtcNow.AddSeconds(60 * 2);
        var canonicalizedresource = path;
        var signedidentifier = keyName;
        var signedversion = "2012-02-12";

        var stringToSign = permissions + "\n" +
                           startTime.ToUniversalTime().ToString("u").Replace(" ", "T") + "\n" +
                           endTime.ToUniversalTime().ToString("u").Replace(" ", "T") + "\n" +
                           canonicalizedresource + "\n" +
                           signedidentifier + "\n" +
                           signedversion;

        HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));

        var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

        return string.Format(CultureInfo.InvariantCulture, "{0}?sp={1}&st={2}&se={3}&spr={4}&sv={5}&sr={6}&si={7}&sig={8}",
            uri,
            permissions,
            startTime.ToUniversalTime().ToString("u").Replace(" ", "T"),
            endTime.ToUniversalTime().ToString("u").Replace(" ", "T"),
            "https",
            signedversion,
            "b",
            keyName,
            HttpUtility.UrlEncode(signature));
    }
2
Can you solve the issue as per the answer below? If yes, please help accept it as answer. Thanks.Ivan Yang

2 Answers

1
votes

Please try the code below, it generates a valid sas token for me:

private static string generateSAS(string resourceUri, string account_name, string key)
{
    var accountName = account_name;
    var accountKey = key;
    var start = DateTime.UtcNow.AddHours(-2).ToString("yyyy-MM-ddTHH:mm:ssZ");
    var end = DateTime.UtcNow.AddHours(2).ToString("yyyy-MM-ddTHH:mm:ssZ");
    var permission = "rwdlac";
    var serviceType = "b";
    var resourceTypes = "sco";
    var protocol = "https";
    var serviceVersion = "2019-02-02";

    //here is the difference from your code.
    var stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n",accountName, permission,serviceType,resourceTypes,start,end,"",protocol,serviceVersion);

    HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
    string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    var sasToken = string.Format("?sv={0}&ss={1}&srt={2}&sp={3}&se={4}&st={5}&spr={6}&sig={7}", serviceVersion,
        serviceType, resourceTypes, permission, end, start, protocol, HttpUtility.UrlEncode(signature));

    var urlToListTables = resourceUri + sasToken;

    return urlToListTables;
}
0
votes

More than likely the issue is with the following line of code:

HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));

Please change it to:

HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(key));