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
ramasubramanian.arramasubramanian.ar 

Amazon S3 signature creation issue - version 4

http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html

I am tying to do a HEAD request. Based on the above document I created the signature but getting 403 forbidden message.
DateTime now = System.now();
String formattednow = now.formatGmt('yyyyMMdd')+'T'+now.formatGmt('hhmmss')+'Z';           
//Canonical string
String a = 'HEAD'+ '\n' + EncodingUtil.urlEncode('/bucketName/fileName.mp4', 'UTF-8') + '\n' + '\n' + 'host:s3.amazonaws.com'+'\n'+'x-amz-date:'+formattednow +'\n' + 'host;x-amz-date'+'\n'+EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', Blob.valueOf('')));
Blob b = Blob.valueOf(a);
String canonical = EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', b));
System.debug('canonical:::--'+canonical);

 //'2015-10-09T06:33:08.090Z'
String StringToSign = 'AWS4-HMAC-SHA256' + '\n' + formattednow + '\n' + '20151009/us-east-1/s3/aws4_request' + '\n' + canonical;

Blob b1 = crypto.generateMac('HmacSHA256',Blob.valueOf('AWS4'+'AWSSECRETKEY'), Blob.valueOf('20151009')); 
Blob b2 = crypto.generateMac('HmacSHA256',b1, Blob.valueOf('us-east-1'));
Blob b3 = crypto.generateMac('HmacSHA256',b2, Blob.valueOf('s3'));
Blob signInKey = crypto.generateMac('HmacSHA256',b3, Blob.valueOf('aws4_request'));
System.debug('AAA:::'+EncodingUtil.convertToHex(Crypto.generateMac('HmacSHA256', Blob.valueOf(StringToSign), signInKey)));

Do you find any mistake in the above code?
Andy BoettcherAndy Boettcher
Ugh Amazon Sig4 creation kicked my butt for weeks.  I ended up getting it to work with SQS, perhaps you can get it to work with S3.
 
String accessKey = 'YOURACCESSKEY';
String secretKey = 'YOURKEYHERE';
String host = 'sqs.us-east-1.amazonaws.com';
String queue = '/SQSQUEUEID/ABC123;
String hashAlgo = 'HmacSHA256';
String url = 'https://'+ host+queue;
String currentDate = getCurrentDate();
String currentDateRaw = getCurrentDateRaw();
String currentDateOnly = getCurrentDateOnly();
String regionName = 'us-east-1';
String serviceName = 'sqs';

////////////////////////////////////
// BODY
////////////////////////////////////

String strBody = '';
strBody+= 'AWSAccessKeyId=' + encode(accessKey);
strBody+= '&Action=SendMessage';
strBody+= '&MessageBody=' + encode(message);
strBody+= '&SignatureMethod=' + hashAlgo;
strBody+= '&SignatureVersion=4';
strBody+= '&Timestamp=' + encode(currentDate);
strBody+= '&Version=2009-02-01';

////////////////////////////////////
// 1 - CANONICAL REQUEST
////////////////////////////////////

String strCanonicalRequest = '';
strCanonicalRequest+='POST\n';
strCanonicalRequest+=queue + '\n';
strCanonicalRequest+='\n';
strCanonicalRequest+='content-type:application/x-www-form-urlencoded; charset=utf-8\n';
strCanonicalRequest+='host:sqs.us-east-1.amazonaws.com\n';
strCanonicalRequest+='x-amz-date:' + currentDate + '\n';
strCanonicalRequest+='\n';
strCanonicalRequest+='content-type;host;x-amz-date';
String strPayloadHash = EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', Blob.valueOf(strBody))); // Payload
strCanonicalRequest+= '\n' + strPayloadHash.toLowerCase();

////////////////////////////////////
// 2 - STRING TO SIGN
////////////////////////////////////

String strStringToSign = '';
strStringToSign+='AWS4-HMAC-SHA256\n';
strStringToSign+=currentDateRaw + '\n';
strStringToSign+=currentDateOnly + '/' + regionName + '/' + serviceName + '/aws4_request';
String strCanonicalHash = EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', Blob.valueOf(strCanonicalRequest))); // Payload
strStringToSign+= '\n' + strCanonicalHash.toLowerCase();

////////////////////////////////////
// 3 - SIGNATURE
////////////////////////////////////

String kSecret = 'AWS4' + secretKey;
Blob kDate = Crypto.generateMac(hashAlgo, Blob.valueOf(currentDateOnly), Blob.valueOf(kSecret));
Blob kRegion = Crypto.generateMac(hashAlgo, Blob.valueOf(regionName), kDate);
Blob kService = Crypto.generateMac(hashAlgo, Blob.valueOf(serviceName), kRegion);
Blob kSigning = Crypto.generateMac(hashAlgo, Blob.valueOf('aws4_request'), kService);
String strSignature = EncodingUtil.convertToHex(Crypto.generateMac(hashAlgo, Blob.valueOf(strStringToSign), kSigning));
strSignature = strSignature.toLowerCase();

////////////////////////////////////
// 4 - AUTHORIZATION HEADER
////////////////////////////////////

String strAuthorizationHeader = 'AWS4-HMAC-SHA256 ';
strAuthorizationHeader+= 'Credential=' + accessKey + '/' + getCurrentDateOnly() + '/' + regionName + '/' + serviceName + '/aws4_request, ';
strAuthorizationHeader+= 'SignedHeaders=content-type;host;x-amz-date, ';
strAuthorizationHeader+= 'Signature=' + strSignature;

// POST
HttpRequest req = new HttpRequest();
req.setEndPoint(url);
req.setHeader('Authorization', strAuthorizationHeader);
req.setHeader('content-type','application/x-www-form-urlencoded; charset=utf-8');
req.setHeader('host', host);
req.setHeader('x-amz-date', currentDate);
req.setMethod('POST');
req.setBody(strBody);

Good luck!