CryptoJS AES 解密返回空白值 - 打字稿

CrytoJS AES decrypt returning a blank value - Typescript

我有以下 Typescript 代码并尝试了一些方法,但我无法使解密工作。将不胜感激。

提前致谢!

import {Injectable} from '@angular/core';
import * as CryptoJS from 'crypto-js';
@Injectable({
  providedIn: 'root'
})
export class UmCryptoService {
  constructor() {
  }
  encrypt<T>(key, value: T): string{
    key = CryptoJS.enc.Utf8.parse(key);
    const i = CryptoJS.enc.Utf8.parse('1583288699248111');
    const ciphertext = CryptoJS.AES.encrypt(JSON.stringify(value), key, {iv: i}).toString();
    console.log('SS cipherText: ' + ciphertext);
    return ciphertext;
  }
  decrypt(key, value){
    key = CryptoJS.enc.Utf8.parse(key);
    const i = CryptoJS.enc.Utf8.parse('1583288699248111');
    const decryptedData = CryptoJS.AES.decrypt(CryptoJS.enc.Base64.parse(value), key, {iv: i});
    console.log('SS utf8 decryptedData: ' + decryptedData.toString(CryptoJS.enc.Utf8));
    return decryptedData.toString(CryptoJS.enc.Utf8);
  }
}

在控制台中,我看到:

LOG: 'SS cipherText: UbNlnYr0qd7ua0TcPTMIyxItPNvNscCfQYIP244Mt/5e7vPHZ1cFDWE9XgV7pA6a'
LOG: 'SS utf8 decryptedData: '

这里有几个单元测试:

it('should encrypt string value', () => {
    const key = '1234567890987654321';
    const strValue = 'Hey check out this encryption!';
    const cipher = service.encrypt(key, strValue);
    console.log('SS: cipher str: ' + cipher);
    expect(cipher).toBeDefined();
    );
  });

fit('should decrypt cipher', fakeAsync (() => {
    const key = '1234567890987654321';
    const cipher = 'UbNlnYr0qd7ua0TcPTMIyxItPNvNscCfQYIP244Mt/5e7vPHZ1cFDWE9XgV7pA6a';
    const strValue = service.decrypt(key, cipher);
    tick(100000);
    console.log('SS: strValue: ' + strValue);
    expect(strValue).toBeDefined();
  }));

密文必须作为 CipherParams 对象或 Base64 编码字符串 (s. The Cipher Input) 传递给 CryptoJS.AES.decrypt(),而不是作为实际代码中的 WordArray (假设 decrypt() 中的 valueencrypt() 的 return 值),即可能的修复是:

const decryptedData = CryptoJS.AES.decrypt(value, key, {iv: i}); 

完整代码:

function encrypt(key, value){
    key = CryptoJS.enc.Utf8.parse(key);
    const i = CryptoJS.enc.Utf8.parse('1583288699248111');
    const ciphertext = CryptoJS.AES.encrypt(JSON.stringify(value), key, {iv: i}).toString();
    //console.log('SS cipherText: ' + ciphertext);
    document.getElementById("ct").innerHTML = 'SS cipherText: ' + ciphertext;
    return ciphertext;
}

function decrypt(key, value){
    key = CryptoJS.enc.Utf8.parse(key);
    const i = CryptoJS.enc.Utf8.parse('1583288699248111');
    const decryptedData = CryptoJS.AES.decrypt(value, key, {iv: i}); // Fix: pass Base64 encoded ciphertext
    //console.log('SS utf8 decryptedData: ' + decryptedData.toString(CryptoJS.enc.Utf8));
    document.getElementById("dt").innerHTML = 'SS utf8 decryptedData: ' + decryptedData.toString(CryptoJS.enc.Utf8);
    return decryptedData.toString(CryptoJS.enc.Utf8);
}

var key = '01234567890123456789012345678901';
var ct = encrypt(key, {test: 'The quick brown fox jumps over the lazy dog'});
var dt = decrypt(key, ct);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="ct"></p>
<p style="font-family:'Courier New', monospace;" id="dt"></p>


请注意,发布的单元测试不适合测试有问题的代码片段,因为在单元测试中 key 作为字符串传递,因此 built-in 密钥派生 被使用,而在代码片段中 key 作为 WordArray 传递,因此密钥被 直接应用 (s. The Cipher Input).所以底层逻辑非常不同。

另外,静态 IV 是不安全的。 (non-secret) IV 应该是 随机each 加密生成并与密文一起传递给解密方 - 通常是串联的。