简体   繁体   中英

How to use crypto-js to save the binary data, of an encryption-output, to a file?

I'm trying to assist a mobile developer with encrypting an image and uploading it to Azure blob storage. The mobile app uses expo and crypto js. I'm not super familiar with mobile dev or expo but it looks like expo gives you access to a base64 encoded version of the image.

My goal is to encrypt that image data, using crypto js, and upload it to Azure blob storage.

The specifics of expo or Azure aren't really that important to my question, but I figure they're worth mentioning. What is important, I think, is that I'm using crypto js to AES encrypt that image data.

I'm starting with a base64 string of image data and so I use crypto js to parse that like follows...

const words = CryptoES.enc.Base64.parse(data);

This gives me a WordArray representing the image data, I think (from the base64 string which the mobile API gives me).

Next I can encrypt that image data like so...

const encrypted = CryptoES.AES.encrypt(words, AES_KEY, { iv: AES_IV });

Now that I have the encrypted data, I would like to write it out to a file in just a binary hex format or whatever. I don't want base64 text in the file and I don't want a hex-string in the file - I'd like it to contain the literal encrypted data byte for byte.

I'm not sure how to get this data.

I guess it's just "toString" but when I do that it says invalid utf8 . This is a JPG file that is being dealt with.

How can I get just the actual byte data and write that to a file with crypto js?

CryptoJS.AES.encrypt() returns a CipherParams object that encapsulates, among others, the ciphertext as WordArray . One possibility is to convert this WordArray to a Uint8Array with a custom method. In the following code this conversion is done by convertWordArrayToUint8Array() :

function convertWordArrayToUint8Array(wordArray) {
    var arrayOfWords = wordArray.hasOwnProperty("words") ? wordArray.words : [];
    var length = wordArray.hasOwnProperty("sigBytes") ? wordArray.sigBytes : arrayOfWords.length * 4;
    var uInt8Array = new Uint8Array(length), index=0, word, i;
    for (i=0; i<length; i++) {
        word = arrayOfWords[i];
        uInt8Array[index++] = word >> 24;
        uInt8Array[index++] = (word >> 16) & 0xff;
        uInt8Array[index++] = (word >> 8) & 0xff;
        uInt8Array[index++] = word & 0xff;
    }
    return uInt8Array;
}

var AES_KEY = CryptoJS.enc.Utf8.parse('0123456789012345');
var AES_IV = CryptoJS.enc.Utf8.parse('5432109876543210');
var plaintext = 'The quick brown fox jumps over the lazy dog';
var ciphertextCP = CryptoJS.AES.encrypt(plaintext, AES_KEY, { iv: AES_IV }); // CipherParams object
var ciphertextWA = ciphertextCP.ciphertext;                                  // WordArray       
var ciphertextArr = convertWordArrayToUint8Array(ciphertextWA);              // Uint8Array

This Uint8Array can now be stored in a file, eg with:

var fileName = "encdata.bin";
saveByteArray([ciphertextArr], fileName);

using saveByteArray() from here .


Another approach is to convert the WordArray to a binary string using the Latin1 encoder :

var ciphertextBinStr = ciphertextWA.toString(CryptoJS.enc.Latin1);

which can then easily be converted to a Uint8Array , eg with:

function str2Uint8Array(str) {
    const arr = new Uint8Array(new ArrayBuffer(str.length));
    for (let i = 0, strLen = str.length; i < strLen; i++)
        arr[i] = str.charCodeAt(i);
    return arr;
}

var ciphertextArr = str2Uint8Array(ciphertextBinStr);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM