Encrypting data blobs

572 views
Skip to first unread message

vincenzoml

unread,
Aug 8, 2012, 10:36:34 AM8/8/12
to sjcl-d...@googlegroups.com
Hi all,

I would like to use SJCL to encrypt blobs returned by the "slice" method documented at http://www.w3.org/TR/FileAPI/#dfn-Blob . I see that I can pass strings to the encryption method of SJCL, but don't understand much more of it. I apologise if the answer is obvious: I do not know javascript that much, just started with it, but would like to see a proof of concept of this idea. And I don't know cryptography that much either...

Thanks

Vincenzo

vincenzoml

unread,
Aug 9, 2012, 10:56:36 AM8/9/12
to sjcl-d...@googlegroups.com
More precisely, it would be enough for me to be able to encrypt and decrypt objects of type TypedArray as described here http://www.khronos.org/registry/typedarray/specs/latest/ . This is useful in HTML5 to read files and encrypt them on the fly.

Vincenzo
  

Justin Thomas

unread,
Aug 9, 2012, 12:07:54 PM8/9/12
to sjcl-d...@googlegroups.com
Hi Vencenzo,

I don't know if this will help, but I'm using SJCL to encrypt (and decrypt in Chrome) files like this:

listeners: {
    change: function(filefield, values, options) {
        var files = filefield.extractFileInput().files

        for (var i = 0, f; f = files[i]; i++) {
            var reader = new FileReader()
            reader.onloadend = (function(theFile) {
                return function(e) {
                    var form = filefield.up('form')
                    $('#attachments').append('<li><em>' + theFile.name + '</em>, ' + theFile.size + ' bytes</li>')

                    var encryption_key = JSON.parse(form.encryption_key)

                    var encrypted_file = sjcl.encrypt(encryption_key, reader.result)
                    var encrypted_name = sjcl.encrypt(encryption_key, theFile.name)

                    if (form.encrypted_attachments === undefined) {
                        form.encrypted_attachments = []
                    }

                    form.encrypted_attachments.push(JSON.stringify({
                        'name': encrypted_name,
                        'data': encrypted_file
                    }))
                };
            })(f);

            reader.readAsBinaryString(f)
        }
    }
}

There's a bit of ExtJS stuff in there, but the key parts are that I'm reading the file in using FileReader and sticking it in my form (to be submitted to the server) just as the string that sjcl.encrypt returns (I'm also encrypting the file name). The decryption is handled using webkit's framework (I haven't found a good way to handle it in Firefox or IE yet, and I suspect I won't until they add support for the FileSystem object):

success: function(response) {
    var json = JSON.parse(response.responseText)
    var filename = sjcl.decrypt(JSON.parse(decryption_key), json.attachment.name)
    var filedata = sjcl.decrypt(JSON.parse(decryption_key), json.attachment.data)

    window.webkitStorageInfo.requestQuota(PERSISTENT, 1024 * 1024 * 5,
    function(grantedBytes) {
        window.requestFileSystem(window.PERSISTENT, grantedBytes,
        function(fs) {
            fs.root.getFile(filename, {
                create: true
            },
            function(fileEntry) {
                fileEntry.createWriter(function(fileWriter) {
                    fileWriter.onwriteend = function(e) {
                        console.log('Write completed.')
                    }

                    fileWriter.onerror = function(e) {
                        console.log('Write failed: ' + e.toString())
                    }
                    var byteArray = new Uint8Array(filedata.length)
                    for (var i = 0; i < filedata.length; i++) {
                        byteArray[i] = filedata.charCodeAt(i) & 0xff
                    }

                    var builder = new BlobBuilder()
                    builder.append(byteArray.buffer)

                    fileWriter.write(builder.getBlob('application/octet-stream'))
                    window.open(fileEntry.toURL())
                },
                errorHandler)
            },
            errorHandler)
        },
        errorHandler)
    },
    function(e) {
        console.log('Error', e)
    })
}

I'm not using slices of Blobs, but perhaps some of the stuff in there can help you.

vincenzoml

unread,
Aug 10, 2012, 7:33:35 AM8/10/12
to sjcl-d...@googlegroups.com


Il giorno giovedì 9 agosto 2012 18:07:54 UTC+2, JT ha scritto:
Hi Vencenzo,
 
There's a bit of ExtJS stuff in there, but the key parts are that I'm reading the file in using FileReader and sticking it in my form (to be submitted to the server) just as the string that sjcl.encrypt returns (I'm also encrypting the file name). The decryption is handled using webkit's framework (I haven't found a good way to handle it in Firefox or IE yet, and I suspect I won't until they add support for the FileSystem object):

Thanks for your reply. At the moment I developed the following solution that works in chrome (v. 18) and firefox (v. 14). I am using the bytes codec which is not enabled by default (I had to enable it using the configure script). As far as I can tell, this still copies data once. It would be very nice to be able to use ArrayBuffers directly in place of the custom type in SJCL. Anyway, here is the code.

    var p = sjcl.json.defaults;
    p.iv = [0,0,0,0];
    p.salt = [];
    var prp = new sjcl.cipher[p.cipher](password);
    
    function encrypt(password,plaintext) {
        var ct = sjcl.mode[p.mode].encrypt(prp, sjcl.codec.bytes.toBits(new Uint8Array(plaintext)), p.iv, p.adata, p.ts);
        return (new Uint8Array(sjcl.codec.bytes.fromBits(ct))).buffer;
    }
    
    function decrypt(password,ciphertext){
        pt = sjcl.mode[p.mode].decrypt(prp, sjcl.codec.bytes.toBits(new Uint8Array(ciphertext)), p.iv, p.adata, p.ts);   
        return(new Uint8Array(sjcl.codec.bytes.fromBits(pt))).buffer;
    }

Question: is it safe to leave iv and salt initialised like that if I know that for each encrypted data block the password will be randomly generated and then encrypted with the file using asymmetric encryption?  Or am I supposed to store the iv and salt in clear together with the ciphertext? Will storing them in clear harm?

The (very well known it seems) idea is:  encrypt data in blocks so that only who knows the private key of the asymmetric encryption can decrypt the data, but decryption is as fast as symmetric encryption. 

Sorry for these naive questions and thanks in advance

Vincenzo



vincenzoml

unread,
Aug 10, 2012, 7:40:13 AM8/10/12
to sjcl-d...@googlegroups.com
I just noticed that (having been using an hardcoded password for testing purposes) I had left prp as a global value and not converted the password from an arraybuffer. That's obviously wrong; for anyone's reference here is the correct code:

    var p = sjcl.json.defaults;
    p.iv = [0,0,0,0];
    p.salt = [];
    
    function encrypt(password,plaintext) {
var prp = new sjcl.cipher[p.cipher](sjcl.codec.bytes.toBits(new Uint8Array(password)));
        var ct = sjcl.mode[p.mode].encrypt(prp, sjcl.codec.bytes.toBits(new Uint8Array(plaintext)), p.iv, p.adata, p.ts);
        return (new Uint8Array(sjcl.codec.bytes.fromBits(ct))).buffer;
    }
    
    function decrypt(password,ciphertext){
var prp = new sjcl.cipher[p.cipher](sjcl.codec.bytes.toBits(new Uint8Array(password)));
Reply all
Reply to author
Forward
0 new messages