【问题标题】:AES crypt Delphi/PHP corrupted outputAES crypt Delphi/PHP 损坏的输出
【发布时间】:2013-08-09 22:35:25
【问题描述】:

我在 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 发送数据?感谢您提供的任何帮助。

【问题讨论】:

    标签: php mysql delphi aes mcrypt


    【解决方案1】:

    看起来像是不同字符集的编码问题。检查您在 delphi 和 php 中使用的字符集。我可以想象你的字符串在 delphi 中是 latin-1,在 php 中是 UTF-8。也因此出现了一些奇怪的符号。

    【讨论】:

    • 我已使用 Notepad++ PHP 文件转换为 ANSI,并修复了其他错误,即接收来自 PHP 脚本的奇怪消息。但是 MySQL 字段仍然有奇怪的字符“�”。我试图将字段编码从 utf8_general_ci 更改为 latin1_general_ci 并且它没有用,仍然出现奇怪的字符。我已通过以下方式修复它: $smth3 = trim($smth3);也许它不是最好的解决方案,但它工作正常,直到我在数据库中存储简单的值。谢谢。
    • 然后是一些奇怪的编码空格。 ;) 这很复杂,您必须提取此字符的代码序列。但很高兴它对你有用
    【解决方案2】:

    这是我的 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));        
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      相关资源
      最近更新 更多