How to encrypt Amazon CloudFront signature to access private content using a complete policy

Has anyone using .net really developed how to successfully sign for use with CloudFront private content? After several days of trying, all I can get is Access Denied.

I worked with variations of the following code, and also tried to use OpenSSL.Net and AWSSDK, but it still does not have a sign method for RSA-SHA1.

The signature (data) is as follows:

{"Statement":[{"Resource":"http://xxxx.cloudfront.net/xxxx.jpg","Condition":​{"DateLessThan":​{"AWS:EpochTime":1266922799}}}]} 

Update: All of this was fixed by deleting one place in the above signature.

If I had noticed this before!

This method attempts to sign a signature for use in a canned URL. Thus, the variations included the chanding padding used in has, as well as canceling the [] byte before signing, since OpenSSL does it this way.

 public string Sign(string data) { using (SHA1Managed SHA1 = new SHA1Managed()) { RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); RSACryptoServiceProvider.UseMachineKeyStore = false; // Amazon PEM converted to XML using OpenSslKey provider.FromXmlString("<RSAKeyValue><Modulus>....."); byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data); byte[] hash = SHA1.ComputeHash(plainbytes); //Array.Reverse(sig); // I have see some examples that reverse the hash byte[] sig = provider.SignHash(hash, "SHA1"); return Convert.ToBase64String(sig); } } 

It is useful to note that I have verified that the content is correctly configured in S3 and CloudFront by creating the CloudFront canning policy URL using my CloudBerry Explorer. How do they do it?

Any ideas would be highly appreciated. Thanks

+7
c # amazon rsa sha1 rsacryptoserviceprovider
source share
3 answers

Here is the complete code if anyone is interested:

 internal class CloudFrontSecurityProvider { private readonly RSACryptoServiceProvider privateKey; private readonly string privateKeyId; private readonly SHA1Managed sha1 = new SHA1Managed(); public CloudFrontSecurityProvider(string privateKeyId, string privateKey) { this.privateKey = new RSACryptoServiceProvider(); RSACryptoServiceProvider.UseMachineKeyStore = false; this.privateKey.FromXmlString( privateKey ); this.privateKeyId = privateKeyId; } private static int GetUnixTime(DateTime time) { DateTime referenceTime = new DateTime(1970, 1,1); return (int) (time - referenceTime).TotalSeconds; } public string GetCannedUrl(string url, DateTime expiration) { string expirationEpoch = GetUnixTime( expiration ).ToString(); string policy = @"{""Statement"":[{""Resource"":""<url>"",""Condition"":{""DateLessThan"":{""AWS:EpochTime"":<expiration>}}}]}". Replace( "<url>", url ). Replace( "<expiration>", expirationEpoch ); string signature = GetUrlSafeString( Sign( policy ) ); return url + string.Format("?Expires={0}&Signature={1}&Key-Pair-Id={2}", expirationEpoch, signature, this.privateKeyId); } private static string GetUrlSafeString(byte[] data) { return Convert.ToBase64String( data ).Replace( '+', '-' ).Replace( '=', '_' ).Replace( '/', '~' ); } private byte[] Sign(string data) { byte[] plainbytes = Encoding.UTF8.GetBytes(data); byte[] hash = sha1.ComputeHash(plainbytes); return this.privateKey.SignHash(hash, "SHA1"); } } 
+6
source share

I made a blog post about what I needed to do to get it working:

http://anthonyvscode.com/2011/01/11/using-amazon-s3-cloudfront-to-distribute-your-private-files/

can help other people solve the problems that I have and run

+3
source share

Now you can do it using the SDK:

http://docs.aws.amazon.com/sdkfornet/v3/apidocs/Index.html

Go to Amazon.CloudFront > AmazonCloudFrontUrlSigner

+2
source share

All Articles