我正在创建一个使用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
我做错了什么?任何人都可以帮我这个吗?
感谢。
答案 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。