2009-06-09 12 views
11

Grundsätzlich möchte ich System.Security.Cryptography.AesManaged (oder eine bessere Klasse, wenn Sie denken, es gibt?), Um ein Byte-Array zu nehmen und ein anderes verschlüsseltes Byte-Array, mit einem gegebenen symmetrischen Schlüssel (ich nehme an, ich ' Ich brauche einen?).Wie kann 'System.Security.Cryptography.AesManaged' verwendet werden, um ein Byte [] zu verschlüsseln?

Ich brauche auch die Möglichkeit, dieses Verfahren umzukehren.

Der Punkt ist, damit ich gespeicherte Passwörter verschlüsseln kann. Ich nehme an, es gibt einen einfachen Weg, dies zu tun?

Dank

Antwort

7

Simple encrypting and decrypting data in C#.

Bearbeiten: Für Kennwörter würde ich empfehlen, BCrypt anstelle einer Zwei-Wege-Verschlüsselung zu verwenden, es sei denn, Sie müssen wirklich das ursprüngliche Kennwort wiederherstellen. Normalerweise braucht man nur die Tatsache, dass jemand das Passwort kennt, nicht das Passwort selbst.

+0

Sieht gut aus, aber was ist ein IV? Ich dachte, ich brauche nur einen 16-Byte-Schlüssel? – Chris

+0

http://en.wikipedia.org/wiki/Initialization_vector. Sie können die Stärke erhöhen, wenn Sie zufälliges Zeug hineinlegen, aber Sie könnten auch Nullen verwenden. –

+0

Ich brauche die Passwörter, um sie an einen anderen Dienst weiterzugeben. – Chris

10

EDIT: Noticed eed3si9n bearbeiten ... Ich stimme zu, symmetrische Verschlüsselung ist eine schlechte Wahl für Kennwörter. Verwenden Sie stattdessen Hashes (und nicht MD5). Hier ist a very complete example.

Ein einfaches Beispiel:

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

ein korrektes Passwort zu bestätigen, würden Sie die gleiche Berechnung über das angegebene Passwort laufen, und vergleichen Sie das Ergebnis an den Hash Sie in Ihrer Datenbank haben.

Es ist gut, Praxis Salz (Zufallsdaten) an die unverschlüsselt hinzuzufügen rainbow table attacks zu vermeiden. Fügen Sie im Grunde einen bekannten, zufällig erzeugten Wert, der für diesen Benutzer eindeutig ist, an den Klartext vor dem Hashing an.

+0

Und eine Klarstellung: Der Salt-Wert muss zusammen mit dem Hash für die späteren Vergleiche gehalten werden. Und generieren Sie jedes Mal ein neues Salz, wenn der Benutzer das Passwort ändert. – devstuff

+3

Ich brauche die Passwörter, um sie an einen anderen Dienst weiterzugeben. – Chris

11

Hier ist, was ich am Ende tat, inspiriert durch (eine ältere Version von) Michael Antwort:

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

Wenn du deinen Code oben angegeben hast, wirst du jedes Mal mit dem gleichen Schlüssel enden, was gut ist, ** aber du wirst auch jedes Mal mit demselben IV enden, was schlecht ist **. Ich bin mir ziemlich sicher, dass die IV spezifisch für die Daten sein soll, die Sie verschlüsseln, während der Schlüssel "global" sein kann. –

0

Die OP erklärt sie die Anmeldeinformationen an einen anderen Dienst übergeben müssen, die als Passwort Speicherung und Verifizierung ein völlig anderes Thema.

Je nachdem, wie viel Kontrolle Sie über den Partner-Service haben oder was sie verfügbar machen, beinhalten die besten Lösungen einen Anbieter oder Industriestandard-Ansätze wie Kerberos, SAML oder andere stabile, sichere Bearer-Token bedeutet Vertrauensstellung. Dies ist ein tiefgehendes Thema.

Aber nehmen wir an, Sie Anmeldeinformationen über Grund Auth SSL/TLS übergeben müssen. Jetzt müssen Sie sie sicher auf reversible Weise aufbewahren. Um dieses Problem zu lösen, hatte ich Erfolg mit dem geheimen Schlüssel, der unter Verwendung eines privaten Zertifikatschlüssels vermittelt wurde. Dies bietet einen gewissen Schutz Ihres geheimen durch das Betriebssystem und ermöglicht OPS Leute die Schlüssel zu verwalten, was wünschenswert ist. Dem Konto, mit dem Ihr Prozess ausgeführt wird, müssen Rechte zum Anzeigen des privaten Schlüssels gewährt werden, wodurch die Vertrauenskette im Betriebssystem beendet wird.

Sie könnten noch über die Schlüsselrotation denken, die Sie benötigen, eine Versionsnummer mit dem Chiffretext zu speichern.Möglicherweise ist SecureString von Interesse, aber bis alle .NET APIs zulassen, dass SecureString als Teil eines Berechtigungsnachweises übergeben wird, kann es vorkommen, dass Sie am Ende eine Zeichenfolge auf dem verwalteten Heap haben, die Sie nicht zerstören können.

Wie auch immer, dies ist kein Löffel gefüttert Antwort mit Code, aber aus Erfahrung, habe ich festgestellt, dass die Verwaltung der Kette von Geheimnissen immer ein Problem ist, und wenn Sie nicht auf einer gehärteten Infrastruktur wie Active Directory, Zertifikate beenden können sind die nächstbeste Sache.

Verwandte Themen