web-dev-qa-db-ja.com

CryptoJSを使用してBase64文字列をデコードする

サーバーに暗号化されたメッセージを送信することを目的とした簡単なWebページを作成しようとしています(そのコンテンツを含むファイルが作成されます)。リンクが作成され、提供されたリンクを受け取ったユーザーは暗号化されたメッセージを見ることができます。値(ファイルの名前とキーを提供するため)。

メッセージは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'変数は単純なString変数ではないため、これも正常です):

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

PHP $ _GET値に基づいているため、文字列を使用する必要があります。これは、Javascriptを使用して再度デコードされます。したがって、私の質問は、文字列をエンコードするためにこれをどのように実行できるかです。そして、結果を文字列としてデコードしましたか?

これは私のengine.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 !");
    }
}
9
aliasbody

私は同様の混乱に遭遇しました、そして参考までに、これが解決策です。

テキスト文字列(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形式と、任意の形式でエンコードされたデータを含む可能性のある文字列との間のインターフェイスです。したがって、フォーマット間で変更するには、どちらかの端にフォーマッターが必要です。1つは解析で、もう1つは文字列化(つまりエンコード)です。この場合、「Hello World」を書くとき、それは特定の形式でエンコードされたテキストであることを覚えておく必要があります(私はUTF-8を想定しています)。

私は this Gist を見つけました。

40
decates