function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Adam PattonAdam Patton 

Generate HmacSHA256 for SAS Token

I am trying to compute a HmacSHA256 Hash using APEX and I cannot get the correct encrypted signiture.  Below is my Apex and the C# example that I am modeling after that works.

Apex:

        datetime dt = datetime.now();

        long epoch = dt.getTime()/1000;

        System.debug('epoch: '+epoch);
        Integer week = 60*60*24*7;
        epoch = epoch+week;
        Integer expiry = epoch.intValue();
        
        System.debug('expiry: '+expiry);
        
        String sasToken = null;
        
        String stringToSign = resourceUri + '\n' + expiry;
        
        String privateKey = EncodingUtil.urlEncode(key, 'UTF-8') ;
        
        Blob privateKeyBlob = Blob.valueOf(EncodingUtil.urlEncode(privateKey, 'UTF-8'));
        Blob urlBlob = Blob.valueOf(EncodingUtil.urlEncode(stringToSign, 'UTF-8'));
        Blob signatureBlob = Crypto.generateMac('HmacSHA256', privateKeyBlob, urlBlob );
        String s = EncodingUtil.base64Encode(signatureBlob);
        
        String signature = EncodingUtil.base64encode(signatureBlob);
      
        sasToken = 'SharedAccessSignature sr=' + EncodingUtil.urlEncode(resourceUri, 'UTF-8') +'&sig=' +
            EncodingUtil.urlEncode(s, 'UTF-8') + '&se=' + expiry + '&skn=' + keyName;

C# Code:

var fromEpochStart = DateTime.UtcNow - new DateTime(1970, 1, 1);
            var expiry = Convert.ToString((int)fromEpochStart.TotalSeconds + 3600);
            var stringToSign = HttpUtility.UrlEncode(baseUrl) + "\n" + expiry;
            var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(sasKeyValue));

            var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
            var sasToken = string.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
                HttpUtility.UrlEncode(baseUrl), HttpUtility.UrlEncode(signature), expiry, sasKeyName);
 
Daniel LaksanaDaniel Laksana
Please try this code below. I have tested and worked:

 
public static String getSasToken(string resourceUri, string keyName, string key) {
        Long expiry = DateTime.now().addDays(1).getTime() / 1000;

        string stringToSign = EncodingUtil.urlEncode(resourceUri,'UTF-8') + '\n' + expiry;
        Blob keyBlob = Blob.valueOf(key);
        Blob urlBlob = Blob.valueOf(stringToSign);
        Blob signature = Crypto.generateMac('HmacSHA256', urlBlob, keyBlob);
        String sasToken = string.format('SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}', new String[]{
            EncodingUtil.urlEncode(resourceUri,'UTF-8'), EncodingUtil.urlEncode(EncodingUtil.base64Encode(signature),'UTF-8'), 
            String.valueOf(expiry), keyName
        });
        //System.debug(sasToken);
        return sasToken;
    }

 
joost karsten 4joost karsten 4
I tested your code and can confirm that it works! Thanks for this, took me quite some time to find out