如何使用预设策略加密 Amazon CloudFront 签名以进行私有内容访问

Posted

技术标签:

【中文标题】如何使用预设策略加密 Amazon CloudFront 签名以进行私有内容访问【英文标题】:How to encrypt Amazon CloudFront signature for private content access using canned policy 【发布时间】:2011-01-18 01:24:18 【问题描述】:

使用 .net 的人是否真正想出了如何成功签署签名以用于 CloudFront 私有内容?经过几天的尝试,我只能得到拒绝访问。

我一直在使用以下代码的变体,还尝试使用 OpenSSL.Net 和 AWSSDK,但它还没有 RSA-SHA1 的签名方法。

签名(数据)如下所示

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

更新:通过删除上述签名中的一个空格来解决所有这些问题。

要是我早点注意到就好了!

此方法尝试对签名进行签名以在预设 url 中使用。因此,其中的一些变体包括更改 has 中使用的填充,以及在签名之前反转 byte[],因为 OpenSSL 就是这样做的。

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);
   

请注意,我已通过使用我的 CloudBerry Explorer 生成 CloudFront 预设策略 URL,验证了 S3 和 CloudFront 中的内容设置是否正确。他们是怎么做到的?

任何想法将不胜感激。谢谢

【问题讨论】:

Chet,能否详细说明您的解决方案?我想在 PostSharp 下载管理器上实现私有内容(现在使用 S3+CloudFront 公共内容)。我对您如何使用 OpenSslKey 将 Amazon PEM 转换为 XML 尤其感兴趣。你能分享一些链接吗?谢谢。 -盖尔 要将 PEM 转换为 XML,您可以从 jensign.com/opensslkey/index.html 获取 OpenSSLKey 的源代码或编译版本。如果您下载,则只需从 cmd 行运行 opensslkey.exe 并按照提示操作 谢谢 - 使用这些信息实施起来并不难。但是,我建议使用一些 GUI 测试 S3/CloudFront 是否正确配置,然后只尝试使用代码做同样的事情。 谢谢,我的政策声明中也有一个额外的空格——这来自 AWS 文档中的示例,该示例还说要准确复制它,包括标点符号和其他文字值 >: ( 【参考方案1】:

如果有人感兴趣,这里是完整的代码:

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");
    


【讨论】:

注意传入的过期时间,需要和UTC时间相关。【参考方案2】:

我已经完成了一篇博客文章,说明我必须做些什么才能让它工作:

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

可能会帮助其他人尝试解决我在启动和运行时遇到的问题

【讨论】:

【参考方案3】:

您现在可以使用 SDK 执行此操作:

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

导航到Amazon.CloudFront &gt; AmazonCloudFrontUrlSigner

【讨论】:

以上是关于如何使用预设策略加密 Amazon CloudFront 签名以进行私有内容访问的主要内容,如果未能解决你的问题,请参考以下文章

使用 amazon sdk 和存储桶策略从 ios 应用程序将图像上传到 amazon s3

如何创建 IAM 策略以根据子网名称标签控制对 Amazon EC2 资源的访问?

Amazon S3 策略只允许上传而不是覆盖 [重复]

近期的技术问题让云供应商进行预设加密

Amazon S3 存储桶策略只允许访问特定的 http

如何在 Amazon S3 中配置 CORS 策略以从 React App 上传文档?