💬

【TypeScript + NestJS】crypto-jsで複合化するとMalformed UTF-8 data になった件

2022/05/27に公開

概要

暗号化した文字列をURLパラメータにセットしてバックエンドと送受信すると以下のエラーが発生した

この記事はエラーの解消までのプロセスを残すものです

https://www.npmjs.com/package/crypto-js

error    Malformed UTF-8 data

環境

  • npm 6.14.13
  • typescript ^4.2.3
  • crypto-js 4.1.1

本題

GitHubで説明されている通りに実装してみたが冒頭のエラーが発生していました。

https://github.com/brix/crypto-js

var CryptoJS = require("crypto-js");

// Encrypt
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();

// Decrypt
var bytes  = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var originalText = bytes.toString(CryptoJS.enc.Utf8);

console.log(originalText); // 'my message'

解消方法

ポイントは複合用の秘密鍵をLatin1 でエンコードする必要があることでした

データがISO-8859-1 でエンコードされていたことからUTF-8ではparseできないよ!!

とのことです。。

ちなみにIssuesにも上がっていたが紹介されている方法では解決しなかったので、今回の解消方法をコメントしておきました。

https://github.com/brix/crypto-js/issues/271

解決したコード

src/utilities/CustomCryptoJs.ts
public getEncodePath(decodePath: string): string {
    const json = CryptoJS.AES.encrypt(
        JSON.stringify(decodePath),
        this.SECRET_KEY
    ).toString()

    return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(json))
}

public getDecodePath(encodePath: string): string {
    const decodePath = decodeURIComponent(encodePath)

    const data = CryptoJS.enc.Base64.parse(decodePath.toString()).toString(
        CryptoJS.enc.Latin1
    )

    const bytes = CryptoJS.AES.decrypt(data, this.SECRET_KEY).toString(
        CryptoJS.enc.Utf8
    )

    return JSON.parse(bytes)
}
GitHubで編集を提案

Discussion