【问题标题】:Delphi/PHP LockBox Encryption AES ECBDelphi/PHP LockBox 加密 AES ECB
【发布时间】:2016-08-05 07:43:41
【问题描述】:

这个问题有几种变体,但我无法确定问题所在。尝试在 PHP 和 Delphi 中加密/解密 我假设我错过了 Delphi 中的一些设置及其与 UTF-8 的关系

使用http://aesencryption.net/ 作为PHP 示例我们试图得到的结果。图像吹
密码 = 123
键 = 测试
128位
加密为 uuIikEZSC9Sa1HAt/XKfGQ==

我希望能够在 Delphi 中解密它
我正在使用 Delphi XE5
与https://github.com/SeanBDurkin/tplockbox
我可以在 Delphi 中使用 encrypt/DeCrypt,但 PHP 加密版本字符串不同

Delphi加密123为vpdeLlfnxTGrSsa2TpbFvg==

这是一个 Delphi 加密的简单示例

function TForm3.EncryptV2(plainText: UTF8String): String;
var CipherText : string;
    FLibrary: TCryptographicLibrary;
    FCodec: TCodec;
begin
  mmo1.Lines.Add('plaintext = ' + plainText);

 FLibrary := TCryptographicLibrary.Create(Self);
  try
    FCodec := TCodec.Create(Self);
    try
      FCodec.CryptoLibrary := FLibrary;
      FCodec.StreamCipherId := BlockCipher_ProgId;
      FCodec.BlockCipherId := Format(AES_ProgId, [256]);
      FCodec.ChainModeId := ECB_ProgId; ;
      FCodec.UTF8Password := 'test';
      FCodec.EncryptString( plainText, CipherText, Tencoding.UTF8 );
      FCodec.Burn;

      result := CipherText;
    finally
      FCodec.Free;
    end;
  finally
    FLibrary.Free;
  end;
end;

解密

function TForm3.DecryptV2(encryptedText: UTF8String): String;
  var plainText : string;
    FLibrary: TCryptographicLibrary;
    FCodec: TCodec;
begin
  FLibrary := TCryptographicLibrary.Create(Self);
  try
    FCodec := TCodec.Create(Self);
    try
      FCodec.CryptoLibrary := FLibrary;
      FCodec.StreamCipherId := BlockCipher_ProgId;
      FCodec.BlockCipherId := Format(AES_ProgId, [256]);
      FCodec.ChainModeId := ECB_ProgId; ;
      FCodec.UTF8Password := 'test';

      mmo1.Lines.Add('Encrypted Text = ' + encryptedText);
      FCodec.DecryptString( plainText, encryptedText,Tencoding.UTF8 );
      mmo1.Lines.Add('DeCrypted Text = ' + plainText);
      result := plainText;
    finally
      FCodec.Free;
    end;
  finally
    FLibrary.Free;
  end;
end;

大家有什么建议吗?

【问题讨论】:

  • 请不要使用 aesencryption.net 作为加密参考,因为它使用了错误模式 (ECB)、错误填充(零填充)并且不支持身份验证。
  • 切勿使用ECB mode。它是确定性的,因此在语义上不安全。您至少应该使用像CBC 或CTR 这样的随机模式。最好对您的密文进行身份验证,以免像padding oracle attack 这样的攻击是不可能的。这可以通过 GCM 或 EAX 等认证模式或encrypt-then-MAC 方案来完成。
  • 我也无法让 Cbc 或任何其他匹配。以为我会先尝试简单的,然后看看其他不匹配的原因是否相同
  • 如果您尝试使用全长键使事情正常工作,则键填充没有标准,它的范围可以从 0x00 字符到内存中键后面的任何垃圾字节。返回并提供一个包含 16 字节完整密钥和完整数据块(同样为 16 字节)的样本,并将结果添加到问题中。使用十六进制对样本数据进行 Base64 编码也使事情变得更加清晰。以十六进制转储输入文本,如果字符串编码为 UTF-8 或 UTF-16,将很清楚。
  • 我会尝试更新问题

标签: php delphi encryption aes lockbox-3


【解决方案1】:

不确定密码箱有什么问题,但这里是使用 OpenSSL 匹配 aesencryption 的代码,OverbyteIcsLibeay 单元来自 ICS 库 http://wiki.overbyte.be/wiki/index.php/ICS_Download

{$APPTYPE CONSOLE}
program aestest;

uses System.SysUtils, System.NetEncoding, OverbyteIcsLibeay;

type
  TKey128 = packed array [0..15] of byte;
  TIV128  = packed array [0..15] of byte;

function AES128EncryptDecrypt(var Source: TBytes; const Key: TKey128;
  const InitializationVector: TIV128; Encrypt: boolean): boolean;
var
  IV: TIV128;
  CipherCtx: PEVP_CIPHER_CTX;
  Dest: TBytes;
  OutLen: Integer;
begin
  Result := False;
  IV := InitializationVector;
  LoadLibeayEx;
  SetLength(Dest, Length(Source) + Length(Key));
  CipherCtx := f_EVP_CIPHER_CTX_new;
  try
    f_EVP_CIPHER_CTX_init(CipherCtx);
    if Encrypt then
    begin
      if f_EVP_EncryptInit_ex(CipherCtx, f_EVP_aes_128_ecb(), nil, @Key[0], @IV[0]) then
      begin
        Result := f_EVP_EncryptUpdate(CipherCtx, @Dest[Low(Dest)], OutLen, @Source[Low(Source)], Length(Source));
        if Result then
          Source := Copy(Dest, Low(Dest), OutLen);
      end;
    end
    else
    begin
      if f_EVP_DecryptInit_ex(CipherCtx, f_EVP_aes_128_ecb(), nil, @Key[0], @IV[0]) then
      begin
        SetLength(Source, Length(Source) + Length(Key));
        Result := f_EVP_DecryptUpdate(CipherCtx, @Dest[Low(Dest)], OutLen, @Source[Low(Source)], Length(Source));
        if Result then
          Source := Copy(Dest, Low(Dest), OutLen);
      end;
    end;
    f_EVP_CIPHER_CTX_cleanup(CipherCtx);
  finally
    f_EVP_CIPHER_CTX_free(CipherCtx);
  end;
end;

function AES128Encrypt(var Source: TBytes; const Key: TKey128;
  const InitializationVector: TIV128): boolean;
begin
  Result := AES128EncryptDecrypt(Source, Key, InitializationVector, True);
end;

function AES128Decrypt(var Source: TBytes; const Key: TKey128;
  const InitializationVector: TIV128): boolean;
begin
  Result := AES128EncryptDecrypt(Source, Key, InitializationVector, False);
end;

const
  DefaultInitializationVector: TIV128 = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

var
  B: TBytes;
  KeyBytes: TBytes;
  KeyPass: TKey128;
begin
  // padding text with zeroes up to 16 bytes
  B := TEncoding.UTF8.GetBytes('123'#0#0#0#0#0#0#0#0#0#0#0#0#0);

  // encrypting
  KeyBytes := TEncoding.UTF8.GetBytes('test');
  Move(KeyBytes[0], KeyPass[0], Length(KeyBytes));
  AES128Encrypt(B, KeyPass, DefaultInitializationVector);
  Writeln(TNetEncoding.Base64.EncodeBytesToString(B));

  // decrypting
  AES128Decrypt(B, KeyPass, DefaultInitializationVector);
  Writeln(TEncoding.UTF8.GetString(B));
end.

此外,f_EVP_aes_128_ecb 函数目前不包含在 OverbyteIcsLibeay 中,因此您需要将此行添加到接口部分

f_EVP_aes_128_ecb         : function: PEVP_CIPHER; cdecl = nil;

这些行到 LoadLibeay 程序

f_EVP_aes_128_ecb := GetProcAddress(GLIBEAY_DLL_Handle, 'EVP_aes_128_ecb');
if not Assigned(f_EVP_aes_128_ecb) then
    raise Exception.Create(Msg + 'EVP_aes_128_ecb');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 2018-07-08
    • 1970-01-01
    相关资源
    最近更新 更多