我尝试了下面的代码(和varients)没有任何成功,也没有找到如何从Delphi调用这些Windows函数的示例。任何线索都会非常感激。
CryptProtectMemory确实会产生一些可能加密的结果,但unprotect根本不会改变那个结果。我怀疑我做了一些愚蠢的事情,但我整天都找不到......
function WinMemEnc(PlnTxt: String): String;
var
Enc: Pointer;
j: Integer;
EncSze: Cardinal;
ws: String;
const
CRYPTPROTECTMEMORY_SAME_PROCESS: Cardinal = 0;
EncryptionBlockSize: Integer = 8;
begin
if Length(PlnTxt) mod EncryptionBlockSize = 0 then
j := Length(PlnTxt)
else
j := ((Length(PlnTxt) div 8) + 1) * 8;
ws := StringofChar(' ', j);
Move(PlnTxt[1], ws[1], j);
Enc := Pointer(ws);
EncSze := j * 2;
if CryptProtectMemory(Enc, EncSze, CRYPTPROTECTMEMORY_SAME_PROCESS) then
begin
Setlength(Result, j);
Move(Enc, Result[1], EncSze);
end;
end;
function WinMemDcr(EncInp: String): String;
var
Enc: Pointer;
j: Integer;
EncSze: Cardinal;
ws: String;
const
CRYPTPROTECTMEMORY_SAME_PROCESS: Cardinal = 0;
begin
j := Length(EncInp);
EncSze := j * 2;
ws := EncInp;
Enc := Pointer(ws);
if CryptUnprotectMemory(Enc, EncSze, CRYPTPROTECTMEMORY_SAME_PROCESS) then
begin
Setlength(Result, j);
Move(Enc, Result[1], EncSze);
end;
end;
答案 0 :(得分:0)
不测试它(纯粹来自代码的外观),我认为问题出在MOVE语句中:
Move(Enc, Result[1], EncSze);
您正在从指针位置移动数据 - 而不是从指针指向的数据移动数据。
你应该使用
Move(Enc^, Result[1], EncSze);
从指针指向POINTED TO的位置移动数据,而不是从指针本身移动数据。
澄清:Enc变量是 - 比如说 - 位于地址$ 12345678,您正在操作的数据位于地址$ 99999999
这意味着地址$ 12345678位于4个字节(99美元99美元99美元和99美元)。在地址$ 99999999处找到您正在操作的数据。
声明
Move(Enc, Result[1], EncSze);
因此将EncSize字节从地址$ 12345678移动到字符串变量Result的第一个字符。这是你不想要的,因为它只会移动$ 99的4个字节,然后是地址$ 1234567C以及之后的任何内容。
要从地址$ 99999999移动数据,您需要告诉编译器,您希望通过指针从POINTED TO位置移动数据,而不是从POINTER本身移动数据:
Move(Enc^, Result[1], EncSze);
但除此之外,我同意大卫的观点。您应该停止使用字符串作为非字符串数据的存储。它会在某个时刻咬你的**。改为使用字节数组(TBytes)。
答案 1 :(得分:0)
您在我的资源库EncryptionBlockSize := 8;
中设置了CRYPTPROTECTMEMORY_BLOCK_SIZE = 16
。
您还错误地将输入字符串的一半移动到ws,因为j
保持字符串的长度,而Move()
移动Count
个字节。 Unicode
Char
为2个字节。
如评论中所述,加密/解密对字节起作用,将加密存储在字符串中是一种潜在的灾难。
所以这是我建议在TBytes中加密/解密带有加密存储的字符串。
function MemEncrypt(const StrInp: String): TBytes;
begin
Result := TEncoding.Unicode.GetBytes(StrInp);
if Length(Result) mod CRYPTPROTECTMEMORY_BLOCK_SIZE <> 0 then
SetLength(Result, ((Length(Result) div CRYPTPROTECTMEMORY_BLOCK_SIZE) + 1) * CRYPTPROTECTMEMORY_BLOCK_SIZE);
if not CryptProtectMemory(Result, Length(Result), CRYPTPROTECTMEMORY_SAME_PROCESS) then
raise Exception.Create('Error Message: '+IntToStr(GetLastError));
end;
function MemDecrypt(const EncInp: TBytes): String;
var
EncTmp: TBytes;
begin
EncTmp := Copy(EncInp);
if CryptUnprotectMemory(EncTmp, Length(EncTmp), CRYPTPROTECTMEMORY_SAME_PROCESS) then
result := TEncoding.Unicode.GetString(EncTmp)
else
raise Exception.Create('Error Message: '+IntToStr(GetLastError));
end;
在解密中,输入TBytes的副本用于保存加密数据。
最后是一个测试程序:
procedure TForm13.Button2Click(Sender: TObject);
const
Txt = '1234567890123456789012345678901';
var
s: string;
b: TBytes;
begin
s := Txt;
Memo1.Lines.Add(s);
b := MemEncrypt(Txt);
s := MemDecrypt(b);
Memo1.Lines.Add(s);
end;