Delphi和NodeJS - 加密字节缓冲区数组(Rijndael密码)

时间:2016-07-12 13:13:45

标签: arrays node.js sockets delphi encryption

我正在创建一个使用Socket进行通信的应用程序(服务器< - >客户端)。

服务器在NodeJS中构建,客户端在Delphi中构建。

使用Rijndael 128位ECB加密服务器端I的数据包。我必须能够对双方进行加密和解密。

这是服务器端NodeJS脚本的示例代码:

var MCrypt = require('mcrypt').MCrypt;

var desEcb = new MCrypt('rijndael-128', 'ecb');
desEcb.open('1234567890123456', 'abcdefghijklmnop'); // key and IV

var encrypted_buffer = desEcb.encrypt(new Buffer([0x4d,0x79,0x20,0x64,0x61,0x74,0x61]));
console.log(encrypted_buffer);

输出缓冲区为:4f ce 37 97 7a dc 11 a9 11 75 97 e6 a3 a4 ae 28

而且,在Delphi中,这是我的代码(我使用DCPCrypt2 lib):

procedure EncryptBuf;
const
  buf: array[0..6] of byte = ($4d, $79, $20, $64, $61, $74, $61);
var
  Cipher : TDCP_Rijndael;
  Key, IV : string;
  data: TByteArray; //32768 bytes
begin
  // Pad Key, IV and Data with zeros as appropriate
  Key := PadWithZeros('1234567890123456', 16);
  IV := PadWithZeros('abcdefghijklmnop', 16);

  // Create the cipher and initialise according to the key length
  Cipher := TDCP_Rijndael.Create(nil);

  Cipher.Init(Key[1], 128, @IV[1]);    {128, 192, 256}

  Cipher.EncryptECB(buf[0], data[0]);

  form1.memo1.lines.add(BufferToHex(data[0], length(data)));

  // Free the cipher and clear sensitive information
  Cipher.Free;
  FillChar(Key[1],Length(Key),0);
end;

但是,我得到的输出缓冲区是:06 03 AA D5 51 EB 2B 8C 24 D5 4E BF D3 55 2E AA

我做错了什么?任何人都可以帮我这个吗?

感谢。

2 个答案:

答案 0 :(得分:1)

您的Node.JS代码使用零块填充(我使用TForge库来检测它):

program Project14;

{$APPTYPE CONSOLE}

uses
  SysUtils, tfTypes, tfBytes, tfCiphers;

procedure Test;
var
  Cipher: TCipher;
  PlainText, EncryptedText, Key, IV: ByteArray;

begin
  Key:= ByteArray.FromText('1234567890123456');
//  IV is not needed in ECB mode
//  IV:=  ByteArray.FromText('abcdefghijklmnop');
  PlainText:= ByteArray.Parse('0x4d,0x79,0x20,0x64,0x61,0x74,0x61', ',');
  Writeln(PlainText.ToHex);

  EncryptedText:= TCipher.AES
//                  .ExpandKey(Key, ECB_ENCRYPT or PADDING_ZERO, IV)
                  .ExpandKey(Key, ECB_ENCRYPT or PADDING_ZERO)
                  .EncryptData(PlainText);
  Writeln(EncryptedText.ToHex);

//  Cipher:= TCipher.AES.ExpandKey(Key, ECB_DECRYPT or PADDING_ZERO, IV);
  Cipher:= TCipher.AES.ExpandKey(Key, ECB_DECRYPT or PADDING_ZERO);
  PlainText:= Cipher.DecryptData(EncryptedText);
  Writeln(PlainText.ToHex);

  readln;
end;

begin
  try
    Test;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

请注意,零填充不允许正确解密(解密数据也用零填充,如上面的代码所示)。

DCPCrypt不支持填充,因此您需要自己填充明文数据。在零填充的情况下很容易 - 只需将明文buf用零填充到16个字节(没有安装DCPCrypt,无法测试)。

答案 1 :(得分:1)

NodeJS脚本使用ECB模式,该模式不使用静态模式。 var名称desEcb之间也存在脱节,这似乎意味着DES加密,但算法被指定为rijndael-128,这实际上是AES加密。

Delphi代码使用ECB模式,该模式不使用iv而是提供。

最好提供正确长度的加密密钥(AES为128,192,256位),因为未指定密钥填充,不同的实现可以自由区分。

通常需要填充,标准为PKCS#7 padding,而不是空填充。请注意,二进制数据不能与空填充一起使用。

注意:不要使用ECB模式,这是不安全的,请参阅ECB mode,向下滚动到企鹅。

而不是ECB模式使用随机iv的CBC模式,只需将iv添加到加密数据中以用于解密。

如果您想通过Cryptomathic在线测试加密AES CALCULATOR