2010-02-17 4 views
7

Est-ce que quelqu'un qui utilise .net a réellement trouvé comment signer avec succès une signature à utiliser avec du contenu privé CloudFront? Après quelques jours de tentatives, tout ce que je peux obtenir est Accès refusé.Comment crypter la signature Amazon CloudFront pour l'accès au contenu privé à l'aide de la politique préenregistrée

J'ai travaillé avec des variantes du code suivant et j'ai également essayé d'utiliser OpenSSL.Net et AWSSDK mais cela n'a pas encore de méthode de signe pour RSA-SHA1.

La signature (données) ressemble à ceci

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

Mise à jour: Résolu tout cela en supprimant un espace unique dans la signature ci-dessus.

Si seulement je l'avais remarqué plus tôt!

Cette méthode tente de signer la signature à utiliser dans l'URL en conserve. Ainsi, parmi les variations, il y a eu le bourrage du padding utilisé dans le has et aussi l'inversion de l'octet [] avant de signer comme 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); 
    } 
} 

Il est utile de noter que j'ai vérifié le contenu est correctement configuré dans S3 et CloudFront en générant une URL de politique en boîte CloudFront en utilisant mon chicouté Explorer. Comment font-ils?

Toutes les idées seraient grandement appréciées. Merci

+0

Chet, pourrait-il expliquer votre solution? Je voudrais implémenter du contenu privé sur le gestionnaire de téléchargement PostSharp (maintenant en utilisant le contenu public S3 + CloudFront). Je suis particulièrement intriguée par la façon dont vous convertissez le PEM Amazon en XML avec OpenSslKey. Pourriez-vous partager un lien avec ceci? Merci. -gael –

+0

Pour convertir le PEM XML vous pouvez saisir la source ou une version comiled de OpenSSLKey de http://www.jensign.com/opensslkey/index.html Si vous téléchargez puis exécutez simplement opensslkey.exe de la ligne cmd et suivez les instructions – Chet

+0

Merci - Ce n'était pas trop difficile à implémenter avec cette info. Cependant, je recommande de tester que S3/CloudFront est correctement configuré à l'aide d'une interface graphique, puis d'essayer de faire la même chose avec du code. –

Répondre

6

Voici le code complet si quelqu'un si vous êtes intéressé:

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

Soyez prudent avec l'expiration temps qui est passé. Il doit être lié à l'heure UTC. – beckelmw

Questions connexes