【问题标题】:AES encode in Delphi XE4 decode in JavascriptDelphi XE4 中的 AES 编码 Javascript 中的解码
【发布时间】:2016-02-25 12:22:32
【问题描述】:

我想在 Delphi XE4 中进行 AES 编码并在 JavaScript 中解码。

我的德尔福代码: (我使用的是 DCPcrypt Cryptographic Component Library v2 Beta 3)

procedure TForm1.Button5Click(Sender: TObject);
var
  Cipher : TDCP_rijndael;
  key: Ansistring;
  data: Ansistring;
  iv: Ansistring; 
begin
  Key := SHA256('password');
  IV :=   'cd6f6eea9a2a59f2';
  Data := '12345678901234567890';

Cipher := TDCP_rijndael.Create(Self);
if Length(Key) <= 16 then
  Cipher.Init(Key[1], 128, @IV[1])
else
  if Length(Key) <= 24 then
    Cipher.Init(Key[1], 192, @IV[1])
  else
    Cipher.Init(Key[1], 256, @IV[1]);
Cipher.EncryptCBC(Data[1],Data[1],Length(Data));

memo1.Lines.Add('DATA_ENC:'+DATA);
memo1.Lines.Add('DATA_BASE64_ENC: '+Base64encode(DATA));

结束;

我的 JavaScript 代码(我使用 CryptoJS):

encypted = 'Pz8/yw0/ck+4tTY/Pn8zPz/f9D8=';  //input base64 text from Delphi routine

var key = CryptoJS.SHA256(CryptoJS.enc.Base64.parse("password"));
var iv  =     CryptoJS.enc.Base64.parse('cd6f6eea9a2a59f2');
var decrypted = CryptoJS.AES.decrypt(encrypted,key,
  keySize: 256,
  iv: iv,
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.ZeroPadding
  });
console.log('DECRYPTED: '+decrypted.toString(CryptoJS.enc.Utf8));

我没有找回原文,请帮助我。怎么回事?

【问题讨论】:

  • 你能通过 DCP 解密结果吗?你得到原文吗?
  • 你为什么使用 CryptoJS.enc.Base64.parse ?只需使用原始字符串。
  • 您是否尝试过加密和解密二进制数据块而不是字符串?我问这个的原因是因为据我所知,字符串在 Delphi 和 JavaScript 中的存储方式有点不同。而且由于加密算法总是使用二进制数据,如果您尝试在 Delphi 和 JavaScript 中加密相同的文本,您会得到不同的结果,因为存储这些字符串的二进制数据是不一样的。
  • 你读过all other questions on using DCPCrypt and Delphi吗?这是一个常见问题,通常是由于混淆了原始数据和 Base64 编码数据、混淆了位和字节大小(我!)、初始化向量或填充的不正确使用(由于遗漏,或者因为库默认使用不同的)。我建议您先这样做,然后用您已尝试/验证的内容以及尚不清楚的内容更新您的问题。
  • 看起来您的加密货币将不安全。如果安全很重要,请聘请专家顾问为您提供建议。

标签: javascript delphi aes delphi-xe4


【解决方案1】:

我对Delphi一无所知,所以我无法帮助你,但我可以说,你的Delphi代码是错误的,因为如果你解析Base64密文并将其编码为十六进制,你会看到:

3f3f3fcb0d3f724fb8b5363f3e7f333f3fdff43f

现代密码的密文应该与随机噪声无法区分,但这个密文看起来相当规则(有很多 0x3f 字节)。


您的 JavaScript 代码到处都是。几乎您使用的每个字符串都有错误的编码。

run.onclick = function(){
  var encrypted = CryptoJS.enc.Base64.parse(inVal.value);

  var key = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse("password"));
  var iv  = CryptoJS.enc.Utf8.parse('cd6f6eea9a2a59f2');
  var decrypted = CryptoJS.AES.decrypt({
    ciphertext: encrypted
  }, key, {
    iv: iv,
    padding: CryptoJS.pad.ZeroPadding
  });
  outHex.innerHTML = decrypted.toString();
  outUtf8.innerHTML = decrypted.toString(CryptoJS.enc.Utf8);
};
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/sha256.js"></script>
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/components/pad-zeropadding-min.js"></script>

<div>Base64 input: <input id="inVal" value="Pz8/yw0/ck+4tTY/Pn8zPz/f9D8="></div>
<div>Decrypted Hex: <span id="outHex">-</span></div>
<div>Decrypted Utf8: <span id="outUtf8">-</span></div>
<div><button id="run">Decrypt</button></div>

当您修复了 Delphi 代码后,您可以在上述可运行的 sn-p 中包含 Base64 并查看是否正确解密。


安全注意事项:

  • 如果您使用相同的密钥发送多个密文,则需要使用随机 IV。如果再次发送相同的消息,攻击者只能通过观察密文才能看到。 IV 不必保密,因此您可以将其与密文一起发送。一种常见的方法是将其添加到密文中并在解密之前将其删除。

  • SHA-256 不足以从低熵密码派生密钥。您应该使用迭代密钥派生函数 (KDF),例如 PBKDF2、bcrypt、scrypt 或 Argon2。查看更多:How to securely hash passwords?

  • 最好对你的密文进行身份验证,这样就不会像padding oracle attack 这样的攻击。这可以通过 GCM 或 EAX 等经过身份验证的模式或encrypt-then-MAC 方案来完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 2014-12-22
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多