Ich versuche, eine Delphi-Version dieses Algorithmus zu erstellen:Was ist falsch an dieser "StretchKey" Implementierung?
void PWSfileV3::StretchKey(const unsigned char *salt, unsigned long saltLen,
const StringX &passkey,
unsigned int N, unsigned char *Ptag)
{
/*
* P' is the "stretched key" of the user's passphrase and the SALT, as defined
* by the hash-function-based key stretching algorithm in
* http://www.schneier.com/paper-low-entropy.pdf (Section 4.1), with SHA-256
* as the hash function, and N iterations.
*/
int passLen = 0;
unsigned char *pstr = NULL;
ConvertString(passkey, pstr, passLen);
unsigned char *X = Ptag;
SHA256 H0;
H0.Update(pstr, passLen);
H0.Update(salt, saltLen);
H0.Final(X);
#ifdef UNICODE
trashMemory(pstr, passLen);
delete[] pstr;
#endif
ASSERT(N >= MIN_HASH_ITERATIONS); // minimal value we're willing to use
for (unsigned int i = 0; i < N; i++) {
SHA256 H;
// The 2nd param in next line was sizeof(X) in Beta-1
// (bug #1451422). This change broke the ability to read beta-1
// generated databases. If this is really needed, we should
// hack the read functionality to try both variants (ugh).
H.Update(X, SHA256::HASHLEN);
H.Final(X);
}
}
Update: (Fehlende Funktion)
void ConvertString(const StringX &text,
unsigned char *&txt,
int &txtlen)
{
LPCTSTR txtstr = text.c_str();
txtlen = text.length();
#ifndef UNICODE
txt = (unsigned char *)txtstr; // don't delete[] (ugh)!!!
#else
#ifdef _WIN32
txt = new unsigned char[3*txtlen]; // safe upper limit
int len = WideCharToMultiByte(CP_ACP, 0, txtstr, txtlen,
LPSTR(txt), 3*txtlen, NULL, NULL);
ASSERT(len != 0);
#else
mbstate_t mbs;
memset(&mbs, '\0', sizeof(mbs));
size_t len = wcsrtombs(NULL, &txtstr, 0, &mbs);
txt = new unsigned char[len+1];
len = wcsrtombs((char *)txt, &txtstr, len, &mbs);
ASSERT(len != (size_t)-1);
#endif
txtlen = len;
txt[len] = '\0';
#endif /* UNICODE */
}
Hier ist, was ich habe (D2009-Version):
(Bitte beachten Sie: T256BitArray als Array definiert ist [0..31] of Byte)
procedure StretchKey(Const Salt:T256BitArray; Const Passkey:string; Const Iterations:LongWord; Var KeyResult:T256BitArray);
var
pStr : RawByteString;
wHash : THash_sha256;
loop : integer;
begin
pStr := AnsiString(PassKey);
wHash := THash_SHA256.Create;
try
wHash.Init;
wHash.Calc(pStr[1], Length(pStr));
wHash.Calc(Salt, Length(Salt));
wHash.Done;
PStr := wHash.DigestStr;
finally
FreeAndNil(wHash);
end;
for loop := 0 to Iterations-1 do
begin
wHash := THash_sha256.Create;
try
wHash.Init;
wHash.Calc(PStr[1], wHash.DigestSize);
wHash.Done;
PStr := wHash.DigestStr;
finally
FreeAndNil(wHash);
end;
end;
move(pStr[1], KeyResult, sizeof(KeyResult));
end;
Das ursprüngliche Code-Snippet stammt aus der Opensource-Anwendung Password Safe.
Ich versuche, eine vorhandene Password Save (v3) -Datenbank zum Lesen zu öffnen.
Es scheint, dass es egal ist, was ich mache Ich kann nicht den Algorithmus den erforderlichen Hash generieren lassen.
Im obigen Delphi-Ausschnitt verwende ich den Komponentensatz DEC v5.2 2009. Ich habe auch die DCPcrypt-Bibliothek ausprobiert. Lustigerweise bekomme ich die gleichen Werte von beiden Bibliotheken, aber nichts ist kompatibel mit dem Hash aus der PWSv3-Datei.
Die SHA256-Komponenten, die ich verwendet habe, bestehen beide die SHA256-Testvektor-Hashes, also nehme ich an, dass ich etwas falsch gemacht habe, wenn ich die Methode umcodiere.
Fehle ich etwas?
Gelöst: Alles ist korrekt. Das Problem tritt bei der Umwandlung der Hauptschlüsselzeichenfolge auf. Ich habe herausgefunden, dass ich die WideCharToMultiByte Funktion verwenden muss, um die richtige Codepage-Konvertierung zu erhalten.
Bevor Sie mit String-Typen und Gießen beginnen Hantieren, lesen Sie in dieser Antwort auf eine ähnliche Frage: http://stackoverflow.com/questions/392657/md5-hashing -in-delphi-2009/736232 # 736232 – mghie
@mghie: Während ich die Tatsache nicht abzählen werde, dass das das Problem sein könnte, wandelt die fehlende Funktion (ich habe es hinzugefügt) die Zeichenkette aus dem ursprünglichen Code um Unicode zu dem, was ich glaube, ist das ANSI-Äquivalent. Trotzdem habe ich alle meine Testfälle mit dem Fiedeln durchgeführt, um zu bestätigen, dass ich das bekomme, was ich über bekannte Testhashes bekommen soll. Ich bin momentan ziemlich zuversichtlich, dass das, was ich so mache, richtig ist. Ich habe das in D2007 ausprobiert und immer noch keine Freude. –
@Ryan: Wenn Sie Ihr Problem gelöst haben, sollten Sie es als Antwort einreichen und akzeptieren. Es könnte sehr hilfreich sein, wenn jemand in Zukunft ein ähnliches Problem hat, um zu sehen, wie Sie das gelöst haben. –