首先,请参阅我在这里使用的 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 演示来查看和使用。这段代码和 Turbo Delphi 2006 和 Delphi 3 一样有效,所以如果你有困难,请检查我评论的关于 Windows XP Base64 实现不尊重 CRYPT_STRING_NOCRLF 的行,因为如果你在 Windows 上,需要更改该行才能使其正常工作。无论如何,对于 OP 的声明意图,我们不希望 $13$10 出现在编码文本中