まず、ここで使用してから使用しているwincryptユニットについては、 このリンクを参照してください。
これが暗号化のために行うことは、入力された文字列を取得し(INIを使用しているので、とにかくすべて単一の文字列ですよね?)、入力されたパスワードに基づいてWinCrypt 3DESを実行します。これにより、バイナリが生成されます。 、Base64で実行します。復号化のために、私はプロセスを逆にします。間違ったパスワードは復号化時にゴミを生成しますが、私がテストした量では、パスワードが両方のステップで正しい限り、正しく機能しているようです。もちろん、クリーンアップを忘れたかもしれませんが、そうであれば簡単に修正できます。
function DecryptStringW(instr, pwd: WideString): WideString;
// password based decryption of a string using WinCrypt API, WideString version
var
Key: TCryptKey;
Hash: TCryptHash;
Prov: TCryptProv;
DataLen, skip, Flags: DWord;
DataBuf: Pointer;
outstr: WideString;
begin
CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
CryptHashData(hash, @pwd[1], Length(Pwd), 0);
CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
CryptDestroyHash(hash);
CryptStringToBinaryW(pointer(instr), Length(instr), CRYPT_STRING_BASE64, nil, DataLen, skip, Flags);
GetMem(databuf, DataLen);
try
CryptStringToBinaryW(pointer(instr), Length(instr), CRYPT_STRING_BASE64, DataBuf,
DataLen, skip, Flags);
CryptDecrypt(Key, nil, True, 0, DataBuf, Datalen);
SetLength(outstr, datalen);
Move(DataBuf^, outstr[1], DataLen);
CryptReleaseContext(Prov, 0);
Result := outstr;
finally
FreeMem(databuf);
end;
end;
function EncryptStringW(instr, pwd: WideString): WideString;
// password based encryption of a string, WideString version
var
Key: TCryptKey;
Hash: TCryptHash;
Prov: TCryptProv;
DataLen, bufsize: DWord;
databuf: PByte;
outstr: WideString;
begin
CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
CryptHashData(hash, @pwd[1], Length(Pwd), 0);
CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
CryptDestroyHash(hash);
bufsize := 0;
DataLen := 0;
CryptEncrypt(Key, nil, True, 0, nil, bufsize, Length(instr));
GetMem(databuf, bufsize);
try
Move(instr[1], databuf^, Length(instr));
DataLen := Length(instr);
CryptEncrypt(Key, nil, True, 0, databuf, DataLen, bufsize);
CryptReleaseContext(Prov, 0);
CryptBinaryToStringW(databuf, DataLen, CRYPT_STRING_BASE64 or
CRYPT_STRING_NOCRLF, nil, bufsize);
SetLength(outstr, bufsize);
CryptBinaryToStringW(databuf, DataLen, CRYPT_STRING_BASE64 or
CRYPT_STRING_NOCRLF, @outstr[1], bufsize);
// result, kill the three characters after the final one the base64 returns ($D$A$0)
// CRYPT_STRING_NOCRLF seems to mean nothing on XP, it might on other systems
// you will need to change to the commented line if you are on Vista, 7, or 8
Result := Copy(outstr, 1, Length(outstr) - 3);
// Result := Outstr;
finally
FreeMem(databuf);
end;
end;
function DecryptStringA(instr, pwd: AnsiString): AnsiString;
// password based decryption of a string using WinCrypt API, ANSI VERSION.
var
Key: TCryptKey;
Hash: TCryptHash;
Prov: TCryptProv;
DataLen, skip, Flags: DWord;
DataBuf: Pointer;
outstr: AnsiString;
begin
CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
CryptHashData(hash, @pwd[1], Length(Pwd), 0);
CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
CryptDestroyHash(hash);
CryptStringToBinaryA(pointer(instr), Length(instr), CRYPT_STRING_BASE64, nil, DataLen, skip, Flags);
GetMem(databuf, DataLen);
try
CryptStringToBinaryA(pointer(instr), Length(instr), CRYPT_STRING_BASE64, DataBuf, DataLen, skip, Flags);
CryptDecrypt(Key, nil, True, 0, DataBuf, Datalen);
SetLength(outstr, datalen);
Move(DataBuf^, outstr[1], DataLen);
CryptReleaseContext(Prov, 0);
Result := outstr;
finally
FreeMem(databuf);
end;
end;
function EncryptStringA(instr, pwd: AnsiString): AnsiString;
// password based encryption of a string, ANSI version
var
Key: TCryptKey;
Hash: TCryptHash;
Prov: TCryptProv;
DataLen, bufsize: DWord;
databuf: PByte;
outstr: AnsiString;
begin
CryptAcquireContext(Prov, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptCreateHash(Prov, CALG_SHA, nil, 0, hash);
CryptHashData(hash, @pwd[1], Length(Pwd), 0);
CryptDeriveKey(Prov, CALG_3DES, hash, 0, key);
CryptDestroyHash(hash);
DataLen := 0;
bufsize := 0;
CryptEncrypt(Key, nil, True, 0, nil, bufsize, Length(instr));
GetMem(databuf, bufsize);
try
Move(instr[1], databuf^, Length(instr));
DataLen := Length(instr);
CryptEncrypt(Key, nil, True, 0, databuf, DataLen, bufsize);
CryptReleaseContext(Prov, 0);
CryptBinaryToStringA(databuf, DataLen, CRYPT_STRING_BASE64 or
CRYPT_STRING_NOCRLF, nil, bufsize);
SetLength(outstr, bufsize);
CryptBinaryToStringA(databuf, DataLen, CRYPT_STRING_BASE64 or
CRYPT_STRING_NOCRLF, @outstr[1], bufsize);
// result, kill the three characters after the final one the base64 returns ($D$A$0)
// CRYPT_STRING_NOCRLF seems to mean nothing on XP, it might on other systems
// you will need to change to the commented line if you are on Vista, 7, or 8
Result := Copy(outstr, 1, Length(outstr) - 3);
// Result := Outstr;
finally
FreeMem(databuf);
end;
end;
簡単な使用例:
procedure TForm1.Button1Click(Sender: TObject);
var
password1: AnsiString;
begin
password1 := 'Test1';
Edit2.Text := EncryptStringA(Edit1.Text, password1);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
password1: AnsiString;
begin
password1 := 'Test1';
Label1.Caption := DecryptStringA(Edit2.Text, password1);
end;
procedure TForm1.Button3Click(Sender: TObject);
var
password1: WideString;
begin
password1 := 'Test1';
Edit2.Text := EncryptStringW(Edit1.Text, password1);
end;
procedure TForm1.Button4Click(Sender: TObject);
var
password1: WideString;
begin
password1 := 'Test1';
Label1.Caption := DecryptStringW(Edit2.Text, password1);
end;
それが誰かを助けることを願っています。
「Edit1」を入力として使用します。暗号化の正しい出力ANSI:3 + Pp7o8aErc =暗号化の正しい出力WideString:HijzDYgRr / Y =
編集:WideStringバージョンも投稿しました。XE3デモをダウンロードして、見て遊んだ。このコードはTurboDelphi2006およびDelphi3と同様に機能するため、問題が発生した場合は、CRYPT_STRING_NOCRLFを尊重しないWindows XP Base64実装についてコメントした行を確認してください。これは、Windowsを使用している場合はこれを正しく機能させるには、行を変更する必要があります。とにかく、OPの表明された意図のために、エンコードされたテキストに$ 13$10が表示されないようにします。