1回のパスでプレーンテキストデータを暗号化およびハッシュしようとしていると思いますか? はいの場合、最初に Hash オブジェクトを作成し、そのハンドルを CryptEncrypt API に渡す必要があります。次に、CryptGetHashParam を使用してハッシュを取得します。
これは疑似コードです (テストされていませんが、進め方がわかります):
procedure doSomeEncryption()
var
HASHOBJ: HCRYPTHASH;
hProv: HCRYPTPROV;
bHash: tBytes;
dwHashBytes: DWORD;
begin
if not CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then
raiseLastOsError;
if not CryptCreateHash(hProv, CALG_SHA, 0, 0, @HASHOBJ) then
raiseLastOsError;
// Your encrypt stuff here
CryptEncrypt(yourHKey, HASHOBJ, ...) //
setLength(bHash, 255); // Allocate the buffer
if CryptGetHashParam(HASHOBJ, HP_HASHVAL, @bHash[0], @dwHashBytes, 0) then
begin
setLength(bHash, dwHashBytes); // bHash now contains the hash bytes
end
else
setLength(bHash, 0);
// Release HASHOBJ
CryptDestroyHash(HASHOBJ);
// Release Provider Context
CryptReleaseContext(hProv, 0);
end;
- 私の擬似コードでは、ほぼすべての Windows API と型 (Crypt API を含む) の変換が含まれているため、 Jedi API プロジェクト (JWA)に依存しています。プロジェクトに含めることができます。
- 疑似コードには、API エラー処理の改善が必要です。
- bHash には、プレーンテキスト バージョンのデータのハッシュが含まれています。ハッシング (および暗号化) はバイト指向の操作であることに注意してください。つまり、文字列エンコーディングを「理解」していません。視覚的には、UTF16、UTF8、および ASCII でエンコードされた同じ文字列値は、異なるバイト表現を持つため、異なるハッシュ値になります。ハッシュ/暗号化するときは、エンコーディングに注意してください。
ところで、この動作は MSDN の CryptEncrypt API について文書化されています。
hHash [入力] ハッシュ オブジェクトへのハンドル。データのハッシュ化と暗号化を同時に行う場合は、ハッシュ オブジェクトへのハンドルを hHash パラメータで渡すことができます。ハッシュ値は、渡されたプレーンテキストで更新されます。このオプションは、署名付きおよび暗号化されたテキストを生成する場合に役立ちます。CryptEncrypt を呼び出す前に、アプリケーションは CryptCreateHash 関数を呼び出して、ハッシュ オブジェクトへのハンドルを取得する必要があります。暗号化が完了したら、CryptGetHashParam 関数を使用してハッシュ値を取得するか、CryptSignHash 関数を使用してハッシュに署名することができます。ハッシュを実行しない場合、このパラメーターは NULL にする必要があります。
アップデート
暗号化後 H1 は、暗号化前のデータのハッシュになります。つまり、H1=HASH('aaa')
復号化後、H2 は復号化されたデータのハッシュ (平文値) になります。
したがって、復号化が成功した場合、H2 は HASH('aaa') と等しくなります。つまり、H1 = H2 です。
H1 & H2 の目的は、データの整合性をチェックすることです。通常、復号化関数は、復号化が成功したかどうかを通知しません。間違ったパスワードでデータを復号化しようとすると、ガベージ バイトが返されます。問題があります-復号化が成功したかどうかを知る方法は? これを行う 1 つの方法は、入力と出力でデータのハッシュを使用することです。それらが一致する場合、復号化は成功しています。ハッシュが異なる場合は、パスワードが間違っているなどの理由で、おそらく復号化が暗黙のうちに失敗した可能性があります。CryptEncrypt/CryptDecrypt は、これらのハッシュを個別にハッシュする代わりに、1 回の操作で取得する便利な方法を提供します。