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

发布于 2024-08-22 03:20:35 字数 1262 浏览 5 评论 0原文

有没有使用 .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 中的内容设置是否正确。他们是如何做到的?

Has anyone using .net actually worked out how to successfully sign a signature to use with CloudFront private content? After a couple of days of attempts all I can get is Access Denied.

I have been working with variations of the following code and also tried using OpenSSL.Net and AWSSDK but that does not have a sign method for RSA-SHA1 yet.

The signature (data) looks like this

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

Update: Solved all of this by removing a single space in the above signature.

If only I had noticed it earlier!

This method attempts to sign the signature for use in the canned url. So of the variations have included chanding the padding used in the has and also reversing the byte[] before signing as apprently OpenSSL do 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's useful to note that I have verified the content is setup correctly in S3 and CloudFront by generating a CloudFront canned policy url using my CloudBerry Explorer. How do they do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谈场末日恋爱 2024-08-29 03:20:35

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

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

}

Here is the full code if anyone if 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");
    }

}
蓝礼 2024-08-29 03:20:35

我已经完成了一篇博客文章,介绍了如何使其正常工作:

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

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

I've done up a blog post of what I had to do to get it working:

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

might help others trying to work out the problems that I had getting it up and running

夏日浅笑〃 2024-08-29 03:20:35

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

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

导航到 Amazon.CloudFront > AmazonCloudFrontUrlSigner

You can now do this using the SDK:

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

Navigate to Amazon.CloudFront > AmazonCloudFrontUrlSigner

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文