Created
September 6, 2018 21:27
-
-
Save jarbacoa/6a4e301cc18f1e708854aa8a4eee29f8 to your computer and use it in GitHub Desktop.
aes client side encryption of files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const fs = require('fs'); | |
| const util = require('util'); | |
| const path = require('path'); | |
| const minimist = require('minimist'); //extract args | |
| const aesjs = require('aes-js'); //encryption | |
| const Buffer = require('buffer/').Buffer; //buffer utils | |
| const toBuffer = require('typedarray-to-buffer'); | |
| // Convert fs.readFile into Promise version of same | |
| const readFile = util.promisify(fs.readFile); | |
| // An example 128-bit key (16 bytes * 8 bits/byte = 128 bits) | |
| // In practice, generate a new key every time. | |
| const key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; | |
| var inputBytes; | |
| var outputBytes; | |
| // encrypt: Encrypts ArrayBuffer with AES CTR. returns cipher Uint8Array | |
| function encrypt(buffer) { | |
| // Convert data to bytes | |
| const dataBytes = aesjs.utils.utf8.toBytes(buffer); | |
| // console.log('DATA BYTES', dataBytes.slice(0, 20), typeof dataBytes); | |
| inputBytes = dataBytes; | |
| // The counter is optional, and if omitted will begin at 1 | |
| const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5)); | |
| const encryptedBytes = aesCtr.encrypt(dataBytes); | |
| return encryptedBytes; | |
| } | |
| // encrypt: decrypts cipher Uint8Array. returns decrypted Uint8Array | |
| function decrypt(encryptedBytes) { | |
| // The counter mode of operation maintains internal state, so to | |
| // decrypt a new instance must be instantiated. | |
| const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5)); | |
| const decryptedBytes = aesCtr.decrypt(encryptedBytes); | |
| // console.log( | |
| // 'DECRYPTED BYTES', | |
| // decryptedBytes.slice(0, 20), | |
| // typeof decryptedBytes | |
| // ); | |
| outputBytes = decryptedBytes; | |
| // Convert our bytes back into text | |
| const decryptedData = aesjs.utils.utf8.fromBytes(decryptedBytes); | |
| return decryptedData; | |
| } | |
| // getFile: Reads file from filepath and outputs as ArrayBuffer | |
| async function getFile(filename) { | |
| const fileBuffer = await readFile(filename); | |
| return fileBuffer; | |
| } | |
| // putFile: Reads binary from ArrayBuffer and outputs as file. | |
| async function outputFile(data, fileExt) { | |
| fs.writeFile(`out/out${fileExt}`, data, function(err) { | |
| if (err) { | |
| return console.log(err); | |
| } | |
| console.log('The file was saved!'); | |
| }); | |
| } | |
| function getFilePath() { | |
| // Get args from input using minimist | |
| const argv = require('minimist')(process.argv.slice(2)); | |
| // Handle incorrect args | |
| try { | |
| if (!argv.f) throw new Error('Supply filepath with flag -f'); | |
| return argv.f; | |
| } catch (err) { | |
| console.log(err.message); | |
| return; | |
| } | |
| } | |
| function diffArray(arr1, arr2) { | |
| var newArr = []; | |
| arr1.map(function(val) { | |
| arr2.indexOf(val) < 0 ? newArr.push(val) : ''; | |
| }); | |
| arr2.map(function(val) { | |
| arr1.indexOf(val) < 0 ? newArr.push(val) : ''; | |
| }); | |
| return newArr; | |
| } | |
| // Main loop | |
| async function main() { | |
| const filePath = getFilePath(); | |
| const fileExt = path.extname(filePath); | |
| // Get File | |
| const inputData = await getFile(filePath); | |
| // Error handling for invalid input file | |
| try { | |
| if (!inputData) throw new Error('Couldn"t get data'); | |
| } catch (err) { | |
| console.log(err.message); | |
| return; | |
| } | |
| // Encrypt data | |
| const encryptedBytes = encrypt(inputData); | |
| // console.log('ENCRYPTED: ', /* encryptedBytes,*/ typeof encryptedBytes); | |
| // Decrypt data | |
| const decryptedData = decrypt(encryptedBytes); | |
| // console.log('DECRYPTED: ', /* decryptedData,*/ typeof decryptedData); | |
| // Reconvert to ArrayBuffer | |
| let outputData = toBuffer(decryptedData); | |
| // Log Input & Output data (ArrayBuffer) | |
| console.log('INPUT BUFFER: ', inputData, typeof inputBytes); | |
| console.log('OUTPUT BUFFER: ', outputData, typeof outputBytes); | |
| // Check Input/Output match for data | |
| console.log( | |
| inputData.slice(0, 1) == outputData.slice(0, 1) | |
| ? 'BUFFER MATCH' | |
| : 'BUFFER NO MATCH', | |
| inputData.slice(0, 1), | |
| outputData.slice(0, 1) | |
| ); | |
| // Check Input/Output match for bytes !!! Issue here | |
| console.log( | |
| inputBytes.slice(0, 1) === outputBytes.slice(0, 1) | |
| ? 'BYTES MATCH' | |
| : 'BYTES NO MATCH', | |
| '\nDiff: ', | |
| diffArray(inputBytes, outputBytes), //no difference but there is still an issue | |
| '\ninputBytes[0,10]: ', | |
| util.inspect(inputBytes.slice(0, 10), false, null, true), | |
| '\noutputBytes[0,10]: ', | |
| util.inspect(outputBytes.slice(0, 10), false, null, true) | |
| ); | |
| // Output file | |
| outputFile(inputData, fileExt); //Outputting input buffer works | |
| // outputFile(outputData, fileExt); //TODO: Outputting output buffer doesn't work. | |
| } | |
| main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment