Wie erzeugt man Rijndael KEY und IV mit einer Passphrase? Die Schlüssellänge muss 256 Bit betragen.
Antworten
Zu viele Anzeigen?Ich denke, Sie suchen nach einer passwortbasierten Schlüsselableitung. Es gibt Rfc2898DeriveBytes
Klasse, die sie implementiert.
Rfc2898DeriveBytes
nimmt ein Passwort, ein Salt und eine Iterationszahl und erzeugt dann Schlüssel durch Aufrufe der GetBytes
Methode.
RFC 2898 enthält Methoden zur Erstellung eines Schlüssels und eines Initialisierungsvektors (IV) aus einem Passwort und einem Salz. Sie können PBKDF2, eine passwortbasierte Schlüsselableitungsfunktion, verwenden, um Schlüssel unter Verwendung einer Pseudozufallsfunktion abzuleiten, die es ermöglicht, Schlüssel von praktisch unbegrenzter Länge zu erzeugen. Die Klasse Rfc2898DeriveBytes kann verwendet werden, um einen abgeleiteten Schlüssel aus einem Basisschlüssel und anderen Parametern zu erzeugen. In einer passwortbasierten Schlüsselableitungsfunktion ist der Basisschlüssel ein Passwort und die anderen Parameter sind ein Salt-Wert und eine Iterationszahl.
Weitere Informationen über PBKDF2 finden Sie in RFC 2898, "PKCS #5: Password-Based Cryptography Specification Version 2.0,".
Beispiel:
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);
}
Sie können verwenden DeriveBytes
in jedem symmetrischen Algorithmus, nicht nur Rijndael
.
Beispiel:
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();
}
}
Verwendung:
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);
}
}
Stellen Sie sicher, dass Sie die salt
y iterations
Parameter.
Dies ist ein Plug-and-Play-Code, den ich im Internet gefunden habe. Es funktioniert einfach:
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();
}
Die IV müssen zufällig sein (es muss kein unvorhersehbarer Zufall sein, nur zufällig genug, damit sie nicht wiederverwendet werden).
Um den Schlüssel aus dem Kennwort zu generieren, suchen Sie nach einem Schlüsselableitungsfunktion für die es heutzutage mindestens drei gute Möglichkeiten gibt (PBKDF2, bcrypt, scrypt), führt die Verwendung eines nicht iterierten Hashes, wie von einem Vorposter vorgeschlagen, eher zu unsicheren Systemen.
Verwenden Sie weder AES noch Rijndael, das ist nicht ganz dasselbe. Die Verwendung einer Rijndael-Kombination, die nicht Teil von AES ist, könnte später ein Alptraum für die Interoperabilität sein, und die Sicherheit dieser Funktionskombination ist ohnehin nicht gut untersucht.
Der IV muss zufällig sein (normalerweise wird er zusammen mit den verschlüsselten Daten übergeben), und der Schlüssel kann auf verschiedene Weise abgeleitet werden: Sie können das Kennwort einfach auf die Länge des Schlüssels auffüllen (wenn das Kennwort kürzer als 32 Zeichen ist) oder (was zuverlässiger ist) einen Schlüssel mit Hilfe des SHA2-Hashing-Algorithmus ableiten oder eine andere, ausgefeiltere Methode verwenden.
Verwenden Sie diese Rfc2898DeriveBytes-Klasse .
Beachten Sie jedoch, dass Ihre Sicherheitsstufe durch die Länge/Stärke der Passphrase verringert/begrenzt ist. Also, tun Sie es nicht.
- See previous answers
- Weitere Antworten anzeigen