2009-06-09 9 views
11

Fondamentalement, je veux utiliser System.Security.Cryptography.AesManaged (ou une meilleure classe, si vous croyez qu'il y en a une?) Pour prendre un tableau d'octets et créer un autre tableau d'octets crypté, en utilisant une clé symétrique donnée (je suppose J'en ai besoin d'un?).Comment utiliser 'System.Security.Cryptography.AesManaged' pour chiffrer un octet []?

J'ai également besoin de la manière d'inverser cette procédure. Le but de ceci est de pouvoir chiffrer les mots de passe stockés. Je suppose qu'il y a un moyen simple de faire cela?

Merci

Répondre

7

Simple encrypting and decrypting data in C#.

Modifier: Pour les mots de passe, je recommande d'utiliser BCrypt au lieu de faire un chiffrement bidirectionnel, sauf si vous avez vraiment besoin de récupérer le mot de passe d'origine. Normalement, vous avez juste besoin du fait que quelqu'un connaissait le mot de passe, pas le mot de passe lui-même.

+0

Ça a l'air bien, mais qu'est-ce qu'un IV? Je pensais que j'avais juste besoin d'une clé de 16 octets? – Chris

+0

http://en.wikipedia.org/wiki/Initialization_vector. Vous pouvez augmenter la force si vous mettez des trucs au hasard, mais vous pouvez aussi utiliser des zéros. –

+0

J'ai besoin des mots de passe pour les transmettre à un autre service. – Chris

10

EDIT: Remarqué éditer eed3si9n ... Je suis d'accord, le chiffrement symétrique est un mauvais choix pour les mots de passe. Utilisez des hachages (et pas MD5) à la place. Voici a very complete example.

Un exemple simple:

byte[] clear = GetCleartext(); 
HashAlgorithm sha2 = SHA256CryptoServiceProvider.Create(); 
byte[] hashed = sha2.ComputeHash(clear); 

Pour valider un mot de passe, vous devez exécuter le même calcul sur le mot de passe fourni et comparer le résultat au hachage que vous avez dans votre base de données.

Il est recommandé d'ajouter du sel (données aléatoires) au texte en clair pour éviter rainbow table attacks. Fondamentalement, ajoutez une valeur générée aléatoirement connue, propre à cet utilisateur, au texte en clair avant le hachage.

+0

Et une précision: la valeur de sel doit être conservée avec le hachage pour les comparaisons ultérieures. Et générer un nouveau sel chaque fois que l'utilisateur change le mot de passe. – devstuff

+3

J'ai besoin des mots de passe pour les transmettre à un autre service. – Chris

11

Voici ce que je l'ai fait à la fin, inspiré par (une ancienne version de) la réponse de michael:

private string Encrypt(string input) 
{ 
    return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input))); 
} 
private byte[] Encrypt(byte[] input) 
{ 
    PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 }); 
    MemoryStream ms = new MemoryStream(); 
    Aes aes = new AesManaged(); 
    aes.Key = pdb.GetBytes(aes.KeySize/8); 
    aes.IV = pdb.GetBytes(aes.BlockSize/8); 
    CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write); 
    cs.Write(input, 0, input.Length); 
    cs.Close(); 
    return ms.ToArray(); 
} 
private string Decrypt(string input) 
{ 
    return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input))); 
} 
private byte[] Decrypt(byte[] input) 
{ 
    PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 }); 
    MemoryStream ms = new MemoryStream(); 
    Aes aes = new AesManaged(); 
    aes.Key = pdb.GetBytes(aes.KeySize/8); 
    aes.IV = pdb.GetBytes(aes.BlockSize/8); 
    CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write); 
    cs.Write(input, 0, input.Length); 
    cs.Close(); 
    return ms.ToArray(); 
} 
+6

Compte tenu de votre code ci-dessus, vous allez vous retrouver avec la même clé à chaque fois, ce qui est bien, ** mais vous aurez aussi la même IV à chaque fois, ce qui est mauvais **. Je suis à peu près sûr que la IV devrait être spécifique aux données que vous cryptez, alors que la clé peut être "globale". –

0

Les États OP, ils doivent passer les pouvoirs à un autre service, ce qui est une question tout à fait différente que le stockage et la vérification mot de passe. En fonction du contrôle que vous exercez sur le service partenaire ou sur ce qu'il expose, les meilleures solutions impliquent des approches standard fournies par le fournisseur ou des normes industrielles telles que Kerberos, SAML ou d'autres moyens de jeton de support stables et sécurisés. C'est un sujet profond. Mais supposons que vous devez transmettre vos informations d'identification via Basic Auth SSL/TLS. Alors maintenant, vous devez les stocker en toute sécurité d'une manière réversible. Pour résoudre ce problème, j'ai réussi la transmission de la clé secrète à l'aide d'une clé privée de certificat. Cela offre une certaine protection de votre secret par le système d'exploitation et permet aux gens OPS de gérer les clés, ce qui est souhaitable. Le compte utilisé pour exécuter votre processus doit avoir le droit de voir la clé privée, qui met ensuite fin à la chaîne de confiance sur le système d'exploitation.

Vous devrez peut-être penser à la rotation des clés, ce qui vous obligera à stocker un numéro de version avec le texte chiffré.En outre, SecureString peut être intéressant, mais jusqu'à ce que toutes les API .NET autorisent la transmission de SecureString dans le cadre d'un droit d'accès, il arrive souvent que vous ne puissiez pas détruire une chaîne sur le tas géré. De toute façon, ce n'est pas une réponse alimentée avec du code, mais par expérience, j'ai trouvé que la gestion de la chaîne de secrets est toujours un problème, et si vous ne pouvez pas terminer à une infrastructure renforcée comme Active Directory, certificats sont la meilleure chose suivante.