Node JS 解密无法在 Ubuntu 服务器上运行

Node JS decipher not working on Ubuntu server

我有一个可以使用密钥的密码器。然后它可以 "encrypt" 和 "decrypt" 字符串。

这是错误:

Error: Unsupported state or unable to authenticate data
0|ts-node  |     at Decipheriv.final (crypto.js:183:26)

这是我的实现:

import crypto from "crypto";


export type CipherType = "aes-128-gcm" | "aes-128-ccm" | "aes-192-gcm" | "aes-192-ccm" | "aes-256-gcm" | "aes-256-ccm";

export class Cipher {
    constructor(private key: string, private config: {
        type: CipherType,
        numAuthTagBytes?: number,
        numIvBytes?: number,
        stringBase?: "base64",
    }) {
        config.numAuthTagBytes = config.numAuthTagBytes || 16;
        config.numIvBytes = config.numIvBytes || 12;
        config.stringBase = config.stringBase || "base64";
        if (config.numAuthTagBytes < 16) { console.warn(`Be careful of short auth tags`); }
        if (config.numIvBytes < 12) { console.warn(`Be careful of short ivs`); }
    }


    public encrypt(msg: string) {
        const {type, numIvBytes, numAuthTagBytes, stringBase} = this.config;
        const iv = crypto.randomBytes(numIvBytes);
        const cipher = crypto.createCipheriv(
            type,
            Buffer.from(this.key, stringBase),
            iv,
            numAuthTagBytes ? { 'authTagLength': numAuthTagBytes } as any : undefined
        );

        return [
            iv.toString(stringBase),
            cipher.update(msg, "utf8", stringBase),
            cipher.final(stringBase),
            (cipher as any).getAuthTag().toString(stringBase)
        ].join("");
    }


    public decrypt(cipherText: string) {
        const {type, numIvBytes, numAuthTagBytes, stringBase} = this.config;
        let authTagCharLength: number = this.bytesToChars(numAuthTagBytes);
        let ivCharLength: number = this.bytesToChars(numIvBytes);

        const authTag = Buffer.from(cipherText.slice(-authTagCharLength), stringBase);
        const iv = Buffer.from(cipherText.slice(0, ivCharLength), stringBase);
        const encryptedMessage = Buffer.from(cipherText.slice(ivCharLength, -authTagCharLength), stringBase);

        const decipher = crypto.createDecipheriv(
            type,
            Buffer.from(this.key, stringBase),
            iv,
            { 'authTagLength': numAuthTagBytes } as any
        );
        (decipher as any).setAuthTag(authTag);

        return [
            decipher.update(encryptedMessage, stringBase, "utf8"),
            decipher.final()
        ].join("");
    }

    private bytesToChars(numBytes) {
        if (this.config.stringBase === "base64") {
            switch (numBytes) {
                case 16: return 24;
                case 12: return 16;
                case 8: return 12;
                case 4: return 8;
                case 0: return 0;
                default: throw new Error("What's the math here?");
            }
        } else {
            throw new Error("TODO: support other string types");
        }
    }
}

它在本地 (MacOS) 运行良好,但在 Ubuntu 服务器上它每次都无法解密。


我做错了什么? Linux 是否可能以不同方式对待字符串?


编辑:我想我已经找到问题 node -v -> v8.10.0

Ubuntu 通常有一个非常旧的 NodeJS 版本。您应该更新您的节点版本:

(来自 https://askubuntu.com/a/548776/461996

# Using Ubuntu
curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
sudo apt-get install -y nodejs

其中 13 是您想要的版本(可能应该是最新版本)