SJCL client-side file encryption

I have a problem with encryption files with SJCL and javascript.

I was able to encrypt text files using the FileReader API and readAsBinaryString. When it comes to pdf / png / .. encryption, the problem is probably due to encoding.

I found that I can use readAsArrayBuffer, which is perfect for this task, so I basically read a file and create a new typed array with new Uint8Array()

, but I don't know exactly how I should encrypt such data.

Here's my code:

/** Convert from an array of bytes to a bitArray. */
function toBitArrayCodec(bytes) {
    var out = [], i, tmp=0;
    for (i=0; i<bytes.length; i++) {
        tmp = tmp << 8 | bytes[i];
        if ((i&3) === 3) {
            out.push(tmp);
            tmp = 0;
        }
    }
    if (i&3) {
        out.push(sjcl.bitArray.partial(8*(i&3), tmp));
    }
    return out;
}

/** Convert from a bitArray to an array of bytes. */
function fromBitArrayCodec(arr) {
    var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;
    for (i=0; i<bl/8; i++) {
        if ((i&3) === 0) {
            tmp = arr[i/4];
        }
        out.push(tmp >>> 24);
        tmp <<= 8;
    }
    return out;
}

var reader = new FileReader();
    reader.readAsArrayBuffer(fileData); //filedata comes from function
    reader.onload = function() {
        var bytes = new Uint8Array(reader.result);
        var bits = toBitArrayCodec(bytes);
        var crypt = sjcl.encrypt("aaaaa", bits);

        var decrypt = sjcl.decrypt("aaaaa", crypt);
        var byteNumbers = fromBitArrayCodec(decrypt);
        var byteArray = new Uint8Array(byteNumbers);
        saveData(byteArray, 'png.png');

      

I am getting the error

Uncaught URIError: URI malformed sjcl.js:12sjcl.codec.utf8String.fromBits sjcl.js:12sjcl.json.decrypt sjcl.js:44reader.onload

      

I need to know how to encrypt uint8array

or another alternative to encrypt files (pdf / png / ..).

+3


source to share


1 answer


It is assumed that the plaintext in sjcl will be utf8 encoded. Encrypting a handcrafted bitArray works because the encryption is done on the bitArray and doesn't need to be decrypted. But at the end of decryption, an encoding step is used that converts the recovered bitArray to utf8string. It doesn't work because it contains non-printable characters, because the source was probably binary.

The solution would be to encode it as Base64 before encryption and convert it back after decryption.



var bytes = new Uint8Array(reader.result);
var bits = toBitArrayCodec(bytes);
var base64bits = sjcl.codec.base64.fromBits(bits); // added
var crypt = sjcl.encrypt("aaaaa", base64bits);

var base64decrypt = sjcl.decrypt("aaaaa", crypt);
var decrypt = sjcl.codec.base64.toBits(base64decrypt); // added
var byteNumbers = fromBitArrayCodec(decrypt);
var byteArray = new Uint8Array(byteNumbers);

      

+2


source







All Articles