CryptoJS javascript AES-128、ECB 加密/解密

Dav*_*ham 5 javascript encryption aes ecb cryptojs

目标:使用 AES-128、ECB、0 填充进行加密和解密的简单CryptoJS 示例。

请参阅下面我的可运行示例。

输入文本是“US0378331005-USD-US-en”,它被加密(希望 AES-128 包含上述所有内容),然后解密(这不起作用)

text: US0378331005-USD-US-en
key: 11A1764225B11AA1
key length: 16
encrypted 951422f8ac8354acf23fbc
decrypted a5126fa0fc3cb4c39a4f3e637be98a73
Run Code Online (Sandbox Code Playgroud)

text: US0378331005-USD-US-en
key: 11A1764225B11AA1
key length: 16
encrypted 951422f8ac8354acf23fbc
decrypted a5126fa0fc3cb4c39a4f3e637be98a73
Run Code Online (Sandbox Code Playgroud)
var text = 'US0378331005-USD-US-en';
var key = '11A1764225B11AA1'; // to ensure AES-128 this has to be 16 bit

console.log('text:', text);
console.log('key:', key);
console.log('key length:', key.length );

text = CryptoJS.enc.Hex.parse(text);
key = CryptoJS.enc.Hex.parse(key);
var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");

var encrypted = CryptoJS.AES.encrypt(text, key, { iv: iv, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
encrypted = encrypted.ciphertext.toString(CryptoJS.enc.Hex);

console.log('encrypted', encrypted);

var decrypted =  CryptoJS.AES.decrypt(encrypted, key, {iv: iv, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });

console.log('decrypted', decrypted.toString() );
Run Code Online (Sandbox Code Playgroud)

Top*_*aco 9

您的代码中有几个错误:

  • 如果明文的大小不对应于块大小的整数倍,则像 ECB 这样的块密码模式总是需要填充,如上面示例中的情况。实际上,应该抛出异常。然而,CryptoJS 会隐式填充 0x00 值,执行加密,并将密文截断为原始明文的长度。这种处理是随意的,(我认为)甚至是一个错误。
    作为修复,必须应用填充。由于您正在谈论 0-padding,因此您可能指的是零填充,即CryptoJS.pad.ZeroPadding。请注意,PKCS#7 填充(默认)更可靠。
  • 您使用十六进制编码器进行密钥导入,因此密钥的 16 个十六进制数字将转换为 8 字节密钥,这不是有效的 AES 密钥(有效的 AES 密钥长度为 16、24 和 32 字节)。但是,由于存在错误,CryptoJS 处理此密钥大小但会产生不符合 AES 的结果。
    例如,作为修复,32 位十六进制数字密钥必须与十六进制编码器结合用于 AES-128。另一种适用于已发布密钥的替代方案是 Utf8 编码器。
  • 明文显然不是十六进制编码的,因此可以不应用十六进制编码器。
    作为修复,将使用 Utf8 编码器。
  • ECB 模式不使用 IV,即 IV 被忽略,因此可以省略。请注意,ECB 模式正是不安全的,因为它不使用 IV。因此,应采用具有IV的模式。
  • 解密期间CryptoJS.AES.decrypt()需要一个CipherParams对象,但在当前代码中传递的是十六进制编码的密文。
    解决方法是CipherParams从十六进制编码的密文创建一个对象并传递它,或者传递 Base64 编码的密文,CryptoJS 将其隐式转换为对象CipherParams。
  • 解密数据的Utf8解码缺失。

固定代码:

var text = 'US0378331005-USD-US-en';
var key = '11A1764225B11AA1'; 

console.log('text:', text);
console.log('key:', key);
console.log('key length:', key.length );

// Fix: Use the Utf8 encoder
text = CryptoJS.enc.Utf8.parse(text); 
// Fix: Use the Utf8 encoder (or apply in combination with the hex encoder a 32 hex digit key for AES-128)
key = CryptoJS.enc.Utf8.parse(key); 

// Fix: Apply padding (e.g. Zero padding). Note that PKCS#7 padding is more reliable and that ECB is insecure
var encrypted = CryptoJS.AES.encrypt(text, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.ZeroPadding }); 
encrypted = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
console.log('encrypted', encrypted);

// Fix: Pass a CipherParams object (or the Base64 encoded ciphertext)
var decrypted =  CryptoJS.AES.decrypt({ciphertext: CryptoJS.enc.Hex.parse(encrypted)}, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.ZeroPadding }); 

// Fix: Utf8 decode the decrypted data
console.log('decrypted', decrypted.toString(CryptoJS.enc.Utf8)); 
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

  • 向您致敬,先生,您对我的问题给出了非常好的、详细的答案。非常感谢! (2认同)