Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
60
rated 0 times [  66] [ 6]  / answers: 1 / hits: 24456  / 8 Years ago, fri, november 18, 2016, 12:00:00

I need to let users load files from their system, encrypt them on-the-fly and upload to the server and do the opposite thing (download files from the server, decrypt on the fly and let the user save them locally). The exact crypto method is not very important although AES is preferred.



Links like Encryption / decryption of binary data in the browser just tell you use CryptoJS but I was unable to find any actually working samples. All samples I found focus on dealing with strings while in binary data you can easily find invalid Unicode sequences.



Is there any working sample I can test which can process files of any kind?


More From » encryption

 Answers
2

Note: I won't explain how to decrypt the data, but that should be rather easy to figure out using the code for encryption and the documentation-links provided.



First of all, the user has to be able to select a file via an input element.



<input type=file id=file-upload onchange=processFile(event)>


You can then load the content of the file using the HTML5 FileReader API



function processFile(evt) {
var file = evt.target.files[0],
reader = new FileReader();

reader.onload = function(e) {
var data = e.target.result;

// to be continued...
}

reader.readAsArrayBuffer(file);
}


Encrypt the acquired data using the WebCrypto API.

If you don't want to randomly generate the key use crypto.subtle.deriveKey to create a key, for example, from a password that the user entered.



// [...]
var iv = crypto.getRandomValues(new Uint8Array(16)); // Generate a 16 byte long initialization vector

crypto.subtle.generateKey({ 'name': 'AES-CBC', 'length': 256 ]}, false, [ 'encrypt', 'decrypt' ])
.then(key => crypto.subtle.encrypt({ 'name': 'AES-CBC', iv }, key, data))
.then(encrypted => { /* ... */ });


Now you can send your encrypted data to the server (e.g. with AJAX).
Obviously you will also have to somehow store the Initialization Vector to later successfully decrypt everything.






Here is a little example which alerts the length of the encrypted data.



Note: If it says Only secure origins are allowed, reload the page with https and try the sample again (This is a restriction of the WebCrypto API):
HTTPS-Link





function processFile(evt) {
var file = evt.target.files[0],
reader = new FileReader();

reader.onload = function(e) {
var data = e.target.result,
iv = crypto.getRandomValues(new Uint8Array(16));

crypto.subtle.generateKey({ 'name': 'AES-CBC', 'length': 256 }, false, ['encrypt', 'decrypt'])
.then(key => crypto.subtle.encrypt({ 'name': 'AES-CBC', iv }, key, data) )
.then(encrypted => {
console.log(encrypted);
alert('The encrypted data is ' + encrypted.byteLength + ' bytes long'); // encrypted is an ArrayBuffer
})
.catch(console.error);
}

reader.readAsArrayBuffer(file);
}

<input type=file id=file-upload onchange=processFile(event)>




[#60007] Thursday, November 17, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
melinal

Total Points: 367
Total Questions: 101
Total Answers: 96

Location: Nauru
Member since Thu, Feb 2, 2023
1 Year ago
;