Comment générer la clé Rijndael et IV en utilisant une phrase secrète?
Comment générer la clé Rijndael et IV en utilisant une phrase secrète? La longueur de clé doit être en 256 bits.
5 réponses
C'est un code plug and play que j'ai trouvé sur internet. Cela fonctionne simplement:
using System.IO;
using System.Security.Cryptography;
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
public static byte[] Encrypt(byte[] plain, string password)
{
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
rijndael.Key = pdb.GetBytes(32);
rijndael.IV = pdb.GetBytes(16);
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(plain, 0, plain.Length);
cryptoStream.Close();
return memoryStream.ToArray();
}
public static byte[] Decrypt(byte[] cipher, string password)
{
MemoryStream memoryStream;
CryptoStream cryptoStream;
Rijndael rijndael = Rijndael.Create();
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
rijndael.Key = pdb.GetBytes(32);
rijndael.IV = pdb.GetBytes(16);
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(cipher, 0, cipher.Length);
cryptoStream.Close();
return memoryStream.ToArray();
}
Je pense que vous recherchez une dérivation de clé basée sur un mot de passe. Il y a une classe Rfc2898DeriveBytes
qui l'implémente.
Rfc2898DeriveBytes
prend un mot de passe, un sel et un nombre d'itérations, puis génère des clés via des appels à la méthode GetBytes
.
La RFC 2898 inclut des méthodes pour créer une clé et un vecteur d'initialisation (IV) à partir d'un mot de passe et d'un sel. Vous pouvez utiliser PBKDF2, une fonction de dérivation de clé basée sur un mot de passe, pour dériver des clés à l'aide d'une fonction pseudo-aléatoire qui permet des clés virtuellement illimitées la longueur doit être généré. La classe Rfc2898DeriveBytes peut être utilisée pour produire une clé dérivée à partir d'une clé de base et d'autres paramètres. Dans une fonction de dérivation de clé basée sur un mot de passe, la clé de base est un mot de passe et les autres paramètres sont une valeur de sel et un nombre d'itérations.
Pour plus d'informations sur PBKDF2, voir RFC 2898, "PKCS #5: Password-Based Cryptography Specification version 2.0,".
Exemple:
public static byte[] CreateKey(string password)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 9872;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
return rfc2898DeriveBytes.GetBytes(32);
}
Vous pouvez utiliser DeriveBytes
dans n'importe quel algorithme symétrique, pas seulement Rijndael
.
Exemple:
public static SymmetricAlgorithm InitSymmetric(SymmetricAlgorithm algorithm, string password, int keyBitLength)
{
var salt = new byte[] { 1, 2, 23, 234, 37, 48, 134, 63, 248, 4 };
const int Iterations = 234;
using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
{
if (!algorithm.ValidKeySize(keyBitLength))
throw new InvalidOperationException("Invalid size key");
algorithm.Key = rfc2898DeriveBytes.GetBytes(keyBitLength / 8);
algorithm.IV = rfc2898DeriveBytes.GetBytes(algorithm.BlockSize / 8);
return algorithm;
}
}
private static byte[] Transform(byte[] bytes, Func<ICryptoTransform> selectCryptoTransform)
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, selectCryptoTransform(), CryptoStreamMode.Write))
cryptoStream.Write(bytes, 0, bytes.Length);
return memoryStream.ToArray();
}
}
Utilisation:
public static void Main()
{
using (var rijndael = InitSymmetric(Rijndael.Create(), "TestPassword", 256))
{
var text = "Some text to encrypt";
var bytes = Encoding.UTF8.GetBytes(text);
var encryptedBytes = Transform(bytes, rijndael.CreateEncryptor);
var decryptedBytes = Transform(encryptedBytes, rijndael.CreateDecryptor);
var decryptedText = Encoding.UTF8.GetString(decryptedBytes);
Debug.Assert(text == decryptedText);
}
}
Assurez-vous de modifier les paramètres salt
et iterations
.
L'IV doit être aléatoire (n'a pas besoin d'être un aléatoire imprévisible, juste assez aléatoire pour qu'ils ne soient pas réutilisés).
En ce qui concerne la génération de la clé à partir du mot de passe, vous recherchez une fonction de dérivation de clé pour laquelle il existe aujourd'hui au moins trois bons choix (PBKDF2, bcrypt, scrypt), l'utilisation d'un hachage non itéré comme une affiche précédente suggère le plus souvent des systèmes non sécurisés.
Utilisez également AES NI Rijndael, ce n'est pas exactement la même chose. À l'aide d'un La combinaison Rijndael ne faisant pas partie d'AES pourrait être un cauchemar d'interopérabilité plus tard, et la sécurité de cette combinaison de fonctions n'est pas bien étudiée de toute façon.
IV doit être aléatoire (vous le transmettez généralement avec les données cryptées), et la clé peut être dérivée de plusieurs façons: il suffit de pad le mot de passe à la longueur de la clé (si le mot de passe est inférieur à 32 caractères) ou (ce qui est plus fiable) dériver une clé en utilisant l'algorithme de hachage SHA2 ou
Utilisez cette classe Rfc2898DeriveBytes.
Mot de conseil cependant, votre niveau de sécurité a chuté/limité par la longueur/la force de la phrase secrète. Donc, ne pas le faire.