使用 CryptoJS 解码 Base64 字符串

2022-08-30 20:15:02

我正在尝试创建一个简单的网页,目标是向服务器发送和加密消息(这将创建一个包含该内容的文件),然后创建一个链接,接收提供的链接的用户将能够看到加密值(因为它提供了文件的名称和密钥)。

消息使用CryptoJS AES加密,结果是Base64编码,之后进行解码,只有加密消息的Base64和加密的消息被发送到服务器,这是使用Javascript完成的。

我的问题是。我有一条消息,让我说“Hello World”,我用Base64编码,它给了我这个:

1ffffffff5a8ae57

如果我将此值发送到一个变量,然后只使用该变量,它会显示一个结果:

// Works !
var test = CryptoJS.enc.Base64.parse("Hello World");
alert(CryptoJS.enc.Base64.stringify(test));

这是正常的。但是,如果我尝试直接编写文本(或者只是做一个toString(),它就不起作用了......这也是正常的,因为'test'变量不是一个简单的字符串变量):

// Doesn't work !
var test = CryptoJS.enc.Base64.parse("Hello World").toString();
alert(CryptoJS.enc.Base64.stringify(test));

但是我需要使用字符串,因为它基于PHP $ _GET值,然后再次使用Javascript进行解码。所以我的问题是,我怎么能这样做,以便对字符串进行编码,然后将结果解码为字符串?

这是我的引擎.js文件:

// Encrypt the message using a generated key
function encrypt(message, key) {
    return CryptoJS.AES.encrypt(message, key);
}

// Encode String to Base64
function encodeBase64(value) {
    return CryptoJS.enc.Base64.parse(value.toString());
}

// Decode String from Base64 Enconding
function decodeBase64(encodedValue) {
    return CryptoJS.enc.Base64.stringify(encodedValue);
}

// Decrypt the message using the generated key
function decrypt(encrypted, key) {
    return CryptoJS.AES.decrypt(encrypted, key).toString(CryptoJS.enc.Utf8);
}

// Generate the random key
function generateKey() {
    return CryptoJS.lib.WordArray.random(16).toString();
}

// Generate the random fileName
function generateFileName() {
    return CryptoJS.lib.WordArray.random(16).toString();
}

// Convert the text on the form with the encrypted version to be sent into the server
function SendMessage(message, FinalURL) {
    if ((message.value).trim()) {
        var xmlhttp = new XMLHttpRequest;
        xmlhttp.open("POST", "index.php", true);
        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        // Generate the Key and Encrypt the Message
        var key             = generateKey();
        var encryptedData   = encrypt(message.value, key);
        var fileName        = generateFileName();      

        xmlhttp.send("fileName=" + fileName + "&encryptedMsg=" + encodeBase64(encryptedData));

        var finalURL = document.URL + "?MessageID=" + fileName + "&Key=" + key;

        FinalURL.innerHTML = "<p>Final URL: <a href=" + finalURL + ">" + finalURL + "</a></p>";
    } else {
        alert("There is no text to be encrypted !");
    }
}

答案 1

我遇到了类似的困惑,作为参考,这是解决方案。

要将文本字符串(UTF-8 编码)转换为 base-64 字符串,您需要:

var textString = 'Hello world'; // Utf8-encoded string
var words = CryptoJS.enc.Utf8.parse(textString); // WordArray object
var base64 = CryptoJS.enc.Base64.stringify(words); // string: 'SGVsbG8gd29ybGQ='

要将 base-64 编码的字符串转换回文本(UTF-8 编码),请执行以下操作:

var base64 = 'SGVsbG8gd29ybGQ=';
var words = CryptoJS.enc.Base64.parse(base64);
var textString = CryptoJS.enc.Utf8.stringify(words); // 'Hello world'

一些解释

CryptoJS文档中给出的示例中可以看出,parse旨在以编码器期望的格式解析字符串(转换为WordArray),而stringify将WordArray转换为字符串。

从文档中:

var words  = CryptoJS.enc.Base64.parse('SGVsbG8sIFdvcmxkIQ==');
var base64 = CryptoJS.enc.Base64.stringify(words); // 'Hello, World!'

WordArray是CryptoJS与格式无关的数据表示。格式化程序(如 Base64 和 Utf8)是此 WordArray 格式与字符串(可能包含以任何格式编码的数据)之间的接口。因此,要在格式之间切换,您需要在两端都有一个格式化程序,一个解析和一个字符串化(即编码)。在这种情况下,您需要记住,当我们编写“Hello World”时,这是以特定格式编码的文本(我假设UTF-8)。

我发现这个要点很有帮助。


答案 2