EDIT: Per Diskussion in den Kommentaren, lassen Sie mich klarstellen, dass dies Server-Seite passieren wird, hinter SSL. Ich beabsichtige nicht, das Hash-Passwort oder das Hashing-Schema dem Client zur Verfügung zu stellen.JavaScript: Wie Rfc2898DeriveBytes wie C# generieren?
Angenommen, wir haben eine vorhandene asp.net-Identitätsdatenbank mit den Standardtabellen (aspnet_Users, aspnet_Roles usw.). Basierend auf meinem Verständnis verwendet der Passwort-Hashing-Algorithmus sha256 und speichert das salt + (Hash-Passwort) als Base64-codierte Zeichenfolge. EDIT: Diese Annahme ist falsch, siehe Antwort unten.
Ich mag die Funktion der Microsoft.AspNet.Identity.Crypto Klasse replizieren VerifyHashedPassword Funktion mit einer JavaScript-Version.
Lassen Sie uns sagen, dass ein Passwort welcome1 und seine asp.net ist gehasht Passwort ADOEtXqGCnWCuuc5UOAVIvMVJWjANOA ist/LoVy0E4XCyUHIfJ7dfSY0Id + uJ20DTtG + A ==
Bisher habe ich die Teile des Verfahrens reproduzieren konnte, dass Holen Sie sich das Salz und den gespeicherten Unterschlüssel.
Wo die C# -Implementierung mehr oder weniger tut dies:
var salt = new byte[SaltSize];
Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, SaltSize);
var storedSubkey = new byte[PBKDF2SubkeyLength];
Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, PBKDF2SubkeyLength);
ich folgend in JavaScript (nicht von einer Strecke elegant):
var hashedPwd = "ADOEtXqGCnWCuuc5UOAVIvMVJWjANOA/LoVy0E4XCyUHIfJ7dfSY0Id+uJ20DTtG+A==";
var hashedPasswordBytes = new Buffer(hashedPwd, 'base64');
var saltbytes = [];
var storedSubKeyBytes = [];
for(var i=1;i<hashedPasswordBytes.length;i++)
{
if(i > 0 && i <= 16)
{
saltbytes.push(hashedPasswordBytes[i]);
}
if(i > 0 && i >16) {
storedSubKeyBytes.push(hashedPasswordBytes[i]);
}
}
Auch hier ist es nicht schön, aber nach dem Ausführen dieses Snippets stimmen die saltbytes und storedSubKeyBytes Byte für Byte überein, was ich im C# -Debugger für salt und storedSubkey sehe.
schließlich in C#, eine Instanz von Rfc2898DeriveBytes wird verwendet, um einen neuen Unterschlüssel zu erzeugen, auf dem Salz basierte und das Passwort zur Verfügung gestellt, etwa so:
byte[] generatedSubkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, PBKDF2IterCount))
{
generatedSubkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
Dies ist, wo ich bin stecken. Ich habe andere Lösungen wie this one versucht, ich habe CryptoJS und Crypto-Bibliotheken von Google und Node verwendet, und meine Ausgabe erzeugt nie etwas, das der C# -Version ähnelt.
(Beispiel:
var output = crypto.pbkdf2Sync(new Buffer('welcome1', 'utf16le'),
new Buffer(parsedSaltString), 1000, 32, 'sha256');
console.log(output.toString('base64'))
erzeugt "LSJvaDM9u7pXRfIS7QDFnmBPvsaN2z7FMXURGHIuqdY =")
Viele der Zeiger I Online-Probleme hinweisen gefunden habe Beteiligung kodieren Mismatches (NodeJS/UTF-8 vs. .NET/UTF -16LE), also habe ich versucht, das Standardcodierungsformat von .NET zu verwenden, aber ohne Erfolg.
Oder ich könnte völlig falsch sein über das, was ich davon ausgehe, dass diese Bibliotheken tun. Aber alle Hinweise in die richtige Richtung würden sehr geschätzt werden.
Versuchen Sie, einen Kennwort-Hash auf dem Client zu generieren und den Hash zur Validierung an den Server zu übergeben? – trailmax
Nein, ich versuche, die Hash-Server-Seite in node.js zu generieren. Im Wesentlichen die Datenbank beibehalten, aber die IIS/asp.net-Schicht für den Knoten austauschen. Ich bin kein Sicherheitsexperte, aber ich würde vorsichtig sein, wenn ich versuche, die Client-Seite mit Passwort-Operationen zu betreiben. – GojiraDeMonstah
Ah, das verdeutlicht meine Bedenken. Ich würde das in Ihrer Frage erwähnen. Sorry, kann nicht wirklich helfen mit JS-Seite der Dinge hier ( – trailmax