我在Delphi中加密一些数据并通过GET将其发送到PHP脚本,然后解密它并将结果添加到MySQL数据库。问题是它有时会在数据末尾添加一个“ ”或更多“ ”。这是代码:
const
URL = 'http://127.0.0.1/script.php?data=';
PACK_SEPARATOR = '|';
KeySize = 32;
BlockSize = 16;
function aes_encrypt(const Data: string; const Key: string; const IV: string) : string;
var
Cipher : TDCP_rijndael;
tempData, tempKey, tempIV : string;
begin
tempKey := PadWithZeros(Key,KeySize);
tempIV := PadWithZeros(IV,BlockSize);
tempData := PadWithZeros(Data,BlockSize);
Cipher := TDCP_rijndael.Create(nil);
if Length(Key) <= 16 then
Cipher.Init(tempKey[1],128,@tempIV[1])
else if Length(Key) <= 24 then
Cipher.Init(tempKey[1],192,@tempIV[1])
else
Cipher.Init(tempKey[1],256,@tempIV[1]);
Cipher.EncryptCBC(tempData[1],tempData[1],Length(tempData));
Cipher.Free;
FillChar(tempKey[1],Length(tempKey),0);
Result := Base64EncodeStr(tempData);
end;
function PadWithZeros(const str : string; size : integer) : string;
var
origsize, i : integer;
begin
Result := str;
origsize := Length(Result);
if ((origsize mod size) <> 0) or (origsize = 0) then
begin
SetLength(Result,((origsize div size)+1)*size);
for i := origsize+1 to Length(Result) do
Result[i] := #0;
end;
end;
function HTTPEncode(const AStr: String): String;
const
NoConversion = ['A'..'Z','a'..'z','*','@','.','_','-'];
var
Sp, Rp: PChar;
begin
SetLength(Result, Length(AStr) * 3);
Sp := PChar(AStr);
Rp := PChar(Result);
while Sp^ <> #0 do
begin
if Sp^ in NoConversion then
Rp^ := Sp^
else
if Sp^ = ' ' then
Rp^ := '+'
else
begin
FormatBuf(Rp^, 3, '%%%.2x', 6, [Ord(Sp^)]);
Inc(Rp,2);
end;
Inc(Rp);
Inc(Sp);
end;
SetLength(Result, Rp - PChar(Result));
end;
packedData := Memo1.Lines.Text + PACK_SEPARATOR + Edit1.Text + PACK_SEPARATOR + Edit2.Text;
encryptedData := aes_encrypt(packedData, KEY, IV);
encryptedData := HTTPEncode(encryptedData);
serverMsg := DownloadFile(URL+encryptedData);
加密前的'packedData'长度约为133.加密后约为200,因此不会破坏某些服务器的GET数据限制。
现在PHP代码:
function aes_decrypt($dataToDecrypt, $key, $iv)
{
$decoded = base64_decode($dataToDecrypt);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
return $decrypted;
}
$packedData = aes_decrypt($_GET['data'], KEY, IV);
$unpacked = explode(PACK_SEPARATOR, $packedData);
$smth1 = $unpacked[0];
$smth2 = $unpacked[1];
$smth3 = $unpacked[2];
$params = array(':thing' => $somevar, ':data1' => $smth1, ':data2' => $smth2, ':data3' => $smth3);
$query = $pdo->prepare('UPDATE one_table SET somedata1 = :data1 , somedata2 = :data2 , somedata3 = :data3 WHERE something = :thing LIMIT 1');
$success = $query->execute($params);
我花了很多时间试图解决这个问题。前段时间我遇到了加密的PHP输出和二进制数据的问题,问题是aes_decrypt函数所以我把它改成了你可以看到上面的内容。现在我不知道问题出在哪里。 Delphi加密,PHP解密或通过GET发送数据?感谢您提供的任何帮助。
答案 0 :(得分:1)
看起来像不同字符集的编码问题。检查你在delphi和php中使用的字符集。我可以想象你的字符串在delphi中是latin-1,在php中是UTF-8。因此,出现了一些奇怪的符号。
答案 1 :(得分:0)
这是我的Delphi XE3和PHP代码:
Delphi XE3代码:
uses IdHash, IdCoderMIME, IdHashMessageDigest,
DCPrijndael, DCPbase64;
function xBase64Encode(const Input: string): AnsiString;
begin
result := TIdEncoderMIME.EncodeString(Input, TEncoding.UTF8);
end;
function xBase64Decode(const Input: AnsiString): string;
begin
result := TIdDecoderMIME.DecodeString(Input, TEncoding.UTF8);
end;
function PadWithZeros(const str: AnsiString; size: integer): AnsiString;
var
origsize, i: integer;
begin
Result := str;
origsize := Length(Result);
if ((origsize mod size) <> 0) or (origsize = 0) then
begin
SetLength(Result, ((origsize div size) + 1) * size);
for i := origsize + 1 to Length(Result) do
Result[i] := #0;
end;
end;
function AES_Rijndael_Encript(xData, xKey, xIV: string): string;
var
Cipher: TDCP_rijndael;
B64, Data, Key, IV: AnsiString;
begin
B64 := xBase64Encode(xData);
// Pad Key, IV and Data with zeros as appropriate
Key := PadWithZeros(AnsiString(xKey), KeySize);
IV := PadWithZeros(AnsiString(xIV), BlockSize);
Data := PadWithZeros(B64, BlockSize);
// Create the cipher and initialise according to the key length
Cipher := TDCP_rijndael.Create(nil);
if Length(AnsiString(xKey)) <= 16 then
Cipher.Init(Key[1], 128, @IV[1])
else if Length(AnsiString(xKey)) <= 24 then
Cipher.Init(Key[1], 192, @IV[1])
else
Cipher.Init(Key[1], 256, @IV[1]);
// Encrypt the data
Cipher.EncryptCBC(Data[1], Data[1], Length(Data));
// Free the cipher and clear sensitive information
Cipher.Free;
FillChar(Key[1], Length(Key), 0);
// Display the Base64 encoded result
Result := Base64EncodeStr(Data);
end;
function AES_Rijndael_Decript(xData, xKey, xIV: string): string;
var
Cipher : TDCP_rijndael;
Data, Key, IV : ansistring;
xResult : string;
begin
// Pad Key and IV with zeros as appropriate
Key := PadWithZeros(ansistring(xKey),KeySize);
IV := PadWithZeros(ansistring(xIV),BlockSize);
// Decode the Base64 encoded string
Data := Base64DecodeStr(ansistring(xData));
// Create the cipher and initialise according to the key length
Cipher := TDCP_rijndael.Create(nil);
if Length(ansistring(xKey)) <= 16 then
Cipher.Init(Key[1],128,@IV[1])
else if Length(ansistring(xKey)) <= 24 then
Cipher.Init(Key[1],192,@IV[1])
else
Cipher.Init(Key[1],256,@IV[1]);
// Decrypt the data
Cipher.DecryptCBC(Data[1],Data[1],Length(Data));
// Free the cipher and clear sensitive information
Cipher.Free;
FillChar(Key[1],Length(Key),0);
// Display the result
Result := Data;
xResult := Trim(Data);
Result := xBase64Decode(xResult);
end;
如何使用用户功能:
boxKey.Text := 'gmAetc4EydWJg2TcnH34';
boxIV.Text := 'AHsq3SCN7usJzqLi';
Memo2.Lines.Text := AES_Rijndael_Encript(Memo1.Lines.Text, boxKey.Text, boxIV.Text);
Memo1.Lines.Text := AES_Rijndael_Decript(Memo2.Lines.Text, boxKey.Text, boxIV.Text);
PHP代码:
public function AES_Rijndael_Decript($data) {
$key = 'gmAetc4EydWJg2TcnH34';
$iv = 'AHsq3SCN7usJzqLi';
return base64_decode(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($data), MCRYPT_MODE_CBC, $iv));
}
public function AES_Rijndael_Encript($data) {
$key = 'gmAetc4EydWJg2TcnH34';
$iv = 'AHsq3SCN7usJzqLi';
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key,base64_encode($data),MCRYPT_MODE_CBC,$iv));
}