2010-02-17 9 views
7

Hat jemand mit .net tatsächlich herausgefunden, wie Sie eine Signatur für die Verwendung mit privaten CloudFront-Inhalten erfolgreich signieren können? Nach ein paar Tagen aller Versuche kann ich nur Zugriff verweigert bekommen.So verschlüsseln Sie die Amazon CloudFront-Signatur für den Zugriff auf private Inhalte mithilfe der vordefinierten Richtlinie

Ich habe mit Variationen des folgenden Codes gearbeitet und auch mit OpenSSL.Net und AWSSDK versucht, aber das hat noch keine Zeichenmethode für RSA-SHA1.

Die Signatur (Daten) sieht wie folgt aus

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

Update: all dies wird gelöst durch einen einzigen Raum in der obigen Unterschrift zu entfernen.

Wenn ich es schon früher bemerkt hätte!

Diese Methode versucht, die Signatur für die Verwendung in der vordefinierten URL zu signieren. So von den Variationen haben chanding die Padding in der hat und auch die Umkehrung des Bytes [] vor der Unterzeichnung als Lehrling OpenSSL tun es so.

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

Sein nützlich zu beachten, dass ich den Inhalt Setup überprüft haben, korrekt in S3 und Cloudfront durch eine Cloudfront in Dosen Politik url Erzeugung mit meinem Cloudberry Explorer ist. Wie machen Sie das?

Alle Ideen würden sehr geschätzt werden. Dank

+0

Chet, Könnte auf Ihrer Lösung näher erläutern? Ich möchte private Inhalte auf dem PostSharp-Download-Manager implementieren (jetzt mit öffentlichem Inhalt von S3 + CloudFront). Ich bin besonders fasziniert, wie Sie die Amazon PEM mit OpenSslKey in XML konvertieren. Könnten Sie einen Link dazu teilen? Danke. -gael –

+0

Um die PEM in XML zu konvertieren, können Sie entweder die Quell- oder die geeichte Version von OpenSSLKey von http://www.jensign.com/opensslkey/index.html herunterladen. Wenn Sie herunterladen, dann führen Sie einfach opensslkey.exe aus die cmd Linie und folgen Sie den Anweisungen – Chet

+0

Danke - Es war nicht zu schwierig, mit dieser Info zu implementieren. Ich empfehle jedoch zu testen, dass S3/CloudFront richtig konfiguriert ist, indem Sie eine GUI verwenden, und dann versuchen Sie nur, dasselbe mit Code zu machen. –

Antwort

6

Hier ist der vollständige Code, wenn jemand bei Interesse:

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

} 
+0

Seien Sie vorsichtig mit dem Ablauf Zeit, die verstrichen ist. Sie muss mit der UTC-Zeit in Beziehung stehen. – beckelmw