From 50995238bd74786484ef2c208cb583d8c740595b Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Tue, 20 Jun 2017 13:03:04 -0700 Subject: [PATCH 01/12] gcm encryption --- frontend/src/fileReceiver.js | 42 ++++++++++++++++-------------------- frontend/src/fileSender.js | 16 ++++++++------ frontend/src/utils.js | 2 +- server/portal_server.js | 2 +- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index d73fae3c..d7fb6a7a 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -54,36 +54,32 @@ class FileReceiver extends EventEmitter { { kty: 'oct', k: location.hash.slice(1), - alg: 'A128CBC', + alg: 'A256GCM', ext: true }, { - name: 'AES-CBC' + name: 'AES-GCM' }, true, ['encrypt', 'decrypt'] ) - ]) - .then(([fdata, key]) => { - const salt = this.salt; - return Promise.all([ - window.crypto.subtle.decrypt( - { - name: 'AES-CBC', - iv: salt - }, - key, - fdata.data - ), - new Promise((resolve, reject) => { - resolve(fdata.fname); - }) - ]); - }) - .catch(err => { - Raven.captureException(err); - return Promise.reject(err); - }); + ]).then(([fdata, key]) => { + const salt = this.salt; + return Promise.all([ + window.crypto.subtle.decrypt( + { + name: 'AES-GCM', + iv: salt, + tagLength: 128 + }, + key, + fdata.data + ), + new Promise((resolve, reject) => { + resolve(fdata.fname); + }) + ]); + }); } } diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index c443443a..ee64ddea 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -7,7 +7,7 @@ class FileSender extends EventEmitter { constructor(file) { super(); this.file = file; - this.iv = window.crypto.getRandomValues(new Uint8Array(16)); + this.iv = window.crypto.getRandomValues(new Uint8Array(12)); } static delete(fileId, token) { @@ -39,12 +39,13 @@ class FileSender extends EventEmitter { return Promise.all([ window.crypto.subtle.generateKey( { - name: 'AES-CBC', - length: 128 + name: 'AES-GCM', + length: 256, + tagLength: 128 }, true, ['encrypt', 'decrypt'] - ), + ).catch(err => console.log('There was an error generating a crypto key')), new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsArrayBuffer(this.file); @@ -57,12 +58,13 @@ class FileSender extends EventEmitter { return Promise.all([ window.crypto.subtle.encrypt( { - name: 'AES-CBC', - iv: this.iv + name: 'AES-GCM', + iv: this.iv, + tagLength: 128 }, secretKey, plaintext - ), + ).catch(err => console.log('Error with encrypting.')), window.crypto.subtle.exportKey('jwk', secretKey) ]); }) diff --git a/frontend/src/utils.js b/frontend/src/utils.js index e17534fa..f46b4f79 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -12,7 +12,7 @@ function ivToStr(iv) { } function strToIv(str) { - const iv = new Uint8Array(16); + const iv = new Uint8Array(12); for (let i = 0; i < str.length; i += 2) { iv[i / 2] = parseInt(str.charAt(i) + str.charAt(i + 1), 16); } diff --git a/server/portal_server.js b/server/portal_server.js index 8684417f..75317117 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -171,5 +171,5 @@ app.listen(conf.listen_port, () => { }); const validateID = route_id => { - return route_id.match(/^[0-9a-fA-F]{32}$/) !== null; + return route_id.match(/^[0-9a-fA-F]{24}$/) !== null; }; From 34c367c49f4a7651c1d553f388eb4f26f9baa575 Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Tue, 20 Jun 2017 14:33:28 -0700 Subject: [PATCH 02/12] added aad encryption --- frontend/src/fileReceiver.js | 8 ++++++-- frontend/src/fileSender.js | 5 ++++- frontend/src/utils.js | 8 +++++++- server/portal_server.js | 19 ++++++++++++++----- server/storage.js | 22 +++++++++++++++++++++- 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index d7fb6a7a..68b651a3 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -1,5 +1,5 @@ const EventEmitter = require('events'); -const { strToIv } = require('./utils'); +const { strToIv, strToUintArr } = require('./utils'); const Raven = window.Raven; @@ -36,6 +36,7 @@ class FileReceiver extends EventEmitter { fileReader.onload = function() { resolve({ data: this.result, + aad: xhr.getResponseHeader('Additional-Data'), fname: xhr .getResponseHeader('Content-Disposition') .match(/=(.+)/)[1] @@ -65,12 +66,15 @@ class FileReceiver extends EventEmitter { ) ]).then(([fdata, key]) => { const salt = this.salt; + console.log(strToUintArr(fdata.aad)); + return Promise.all([ window.crypto.subtle.decrypt( { name: 'AES-GCM', iv: salt, - tagLength: 128 + tagLength: 128, + additionalData: strToUintArr(fdata.aad) }, key, fdata.data diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index ee64ddea..e8f0402e 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -8,6 +8,7 @@ class FileSender extends EventEmitter { super(); this.file = file; this.iv = window.crypto.getRandomValues(new Uint8Array(12)); + this.aad = window.crypto.getRandomValues(new Uint8Array(6)); } static delete(fileId, token) { @@ -60,7 +61,8 @@ class FileSender extends EventEmitter { { name: 'AES-GCM', iv: this.iv, - tagLength: 128 + tagLength: 128, + additionalData: this.aad }, secretKey, plaintext @@ -77,6 +79,7 @@ class FileSender extends EventEmitter { const fd = new FormData(); fd.append('fname', file.name); fd.append('data', blob, file.name); + fd.append('aad', this.aad); const xhr = new XMLHttpRequest(); diff --git a/frontend/src/utils.js b/frontend/src/utils.js index f46b4f79..9f8f6f9b 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -20,6 +20,7 @@ function strToIv(str) { return iv; } + function notify(str) { if (!('Notification' in window)) { return; @@ -32,8 +33,13 @@ function notify(str) { } } +function strToUintArr(str) { + return new Uint8Array(str.split(",").map(x => parseInt(x))); +} + module.exports = { ivToStr, strToIv, - notify + notify, + strToUintArr }; diff --git a/server/portal_server.js b/server/portal_server.js index 75317117..c966e882 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -78,14 +78,17 @@ app.get('/assets/download/:id', (req, res) => { return; } - storage - .filename(id) - .then(reply => { + Promise.all([ + storage.filename(id), + storage.aad(id)]) + .then(([reply, aad]) => { storage.length(id).then(contentLength => { + res.writeHead(200, { 'Content-Disposition': 'attachment; filename=' + reply, 'Content-Type': 'application/octet-stream', - 'Content-Length': contentLength + 'Content-Length': contentLength, + 'Additional-Data': aad }); const file_stream = storage.get(id); @@ -142,16 +145,22 @@ app.post('/upload/:id', (req, res, next) => { } req.pipe(req.busboy); + + req.busboy.on('field', (fieldname, value) => { + storage.setField(req.params.id, fieldname, value); + }) + req.busboy.on('file', (fieldname, file, filename) => { log.info('Uploading:', req.params.id); const protocol = conf.env === 'production' ? 'https' : req.protocol; const url = `${protocol}://${req.get('host')}/download/${req.params.id}/`; - storage.set(req.params.id, file, filename, url).then(linkAndID => { res.json(linkAndID); }); }); + + }); app.get('/__lbheartbeat__', (req, res) => { diff --git a/server/storage.js b/server/storage.js index dedf0040..f90d4f07 100644 --- a/server/storage.js +++ b/server/storage.js @@ -27,6 +27,8 @@ if (conf.s3_bucket) { length: awsLength, get: awsGet, set: awsSet, + aad: aad, + setField: setField, delete: awsDelete, forceDelete: awsForceDelete, ping: awsPing @@ -38,6 +40,8 @@ if (conf.s3_bucket) { length: localLength, get: localGet, set: localSet, + aad: aad, + setField: setField, delete: localDelete, forceDelete: localForceDelete, ping: localPing @@ -68,6 +72,22 @@ function exists(id) { }); } +function setField(id, key, value) { + redis_client.hset(id, key, value); +} + +function aad(id) { + return new Promise((resolve, reject) => { + redis_client.hget(id, 'aad', (err, reply) => { + if (!err) { + resolve(reply); + } else { + reject(); + } + }) + }) +} + function localLength(id) { return new Promise((resolve, reject) => { try { @@ -86,7 +106,7 @@ function localSet(id, file, filename, url) { return new Promise((resolve, reject) => { const fstream = fs.createWriteStream(path.join(__dirname, '../static', id)); file.pipe(fstream); - fstream.on('close', () => { + fstream.on('close', () => { const uuid = crypto.randomBytes(10).toString('hex'); redis_client.hmset([id, 'filename', filename, 'delete', uuid]); From 4cb34844aaa7f715aabf2ee4e4e74dd20b818ee7 Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Wed, 28 Jun 2017 11:30:14 -0700 Subject: [PATCH 03/12] use 128-bit GCM --- frontend/src/fileReceiver.js | 12 +++++------- frontend/src/fileSender.js | 10 ++++------ frontend/src/utils.js | 17 ++++++----------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index 68b651a3..8bf44ab3 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -1,12 +1,12 @@ const EventEmitter = require('events'); -const { strToIv, strToUintArr } = require('./utils'); +const { hexToArray } = require('./utils'); const Raven = window.Raven; class FileReceiver extends EventEmitter { constructor() { super(); - this.salt = strToIv(location.pathname.slice(10, -1)); + this.salt = hexToArray(location.pathname.slice(10, -1)); } download() { @@ -55,7 +55,7 @@ class FileReceiver extends EventEmitter { { kty: 'oct', k: location.hash.slice(1), - alg: 'A256GCM', + alg: 'A128GCM', ext: true }, { @@ -66,15 +66,13 @@ class FileReceiver extends EventEmitter { ) ]).then(([fdata, key]) => { const salt = this.salt; - console.log(strToUintArr(fdata.aad)); - + return Promise.all([ window.crypto.subtle.decrypt( { name: 'AES-GCM', iv: salt, - tagLength: 128, - additionalData: strToUintArr(fdata.aad) + additionalData: hexToArray(fdata.aad) }, key, fdata.data diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index e8f0402e..a4709d28 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -1,5 +1,5 @@ const EventEmitter = require('events'); -const { ivToStr } = require('./utils'); +const { arrayToHex } = require('./utils'); const Raven = window.Raven; @@ -41,8 +41,7 @@ class FileSender extends EventEmitter { window.crypto.subtle.generateKey( { name: 'AES-GCM', - length: 256, - tagLength: 128 + length: 128 }, true, ['encrypt', 'decrypt'] @@ -61,7 +60,6 @@ class FileSender extends EventEmitter { { name: 'AES-GCM', iv: this.iv, - tagLength: 128, additionalData: this.aad }, secretKey, @@ -73,13 +71,13 @@ class FileSender extends EventEmitter { .then(([encrypted, keydata]) => { return new Promise((resolve, reject) => { const file = this.file; - const fileId = ivToStr(this.iv); + const fileId = arrayToHex(this.iv); const dataView = new DataView(encrypted); const blob = new Blob([dataView], { type: file.type }); const fd = new FormData(); fd.append('fname', file.name); fd.append('data', blob, file.name); - fd.append('aad', this.aad); + fd.append('aad', arrayToHex(this.aad)); const xhr = new XMLHttpRequest(); diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 9f8f6f9b..39f058ca 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -1,4 +1,4 @@ -function ivToStr(iv) { +function arrayToHex(iv) { let hexStr = ''; for (const i in iv) { if (iv[i] < 16) { @@ -11,8 +11,8 @@ function ivToStr(iv) { return hexStr; } -function strToIv(str) { - const iv = new Uint8Array(12); +function hexToArray(str) { + const iv = new Uint8Array(str.length / 2); for (let i = 0; i < str.length; i += 2) { iv[i / 2] = parseInt(str.charAt(i) + str.charAt(i + 1), 16); } @@ -33,13 +33,8 @@ function notify(str) { } } -function strToUintArr(str) { - return new Uint8Array(str.split(",").map(x => parseInt(x))); -} - module.exports = { - ivToStr, - strToIv, - notify, - strToUintArr + arrayToHex, + hexToArray, + notify }; From 05fe534e14bbac2a65c8e8c1299aeaa6004ccb22 Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Thu, 29 Jun 2017 10:27:36 -0700 Subject: [PATCH 04/12] use header for file metadata --- frontend/src/fileReceiver.js | 9 ++++---- frontend/src/fileSender.js | 3 +-- server/portal_server.js | 30 ++++++++++++------------- server/storage.js | 43 +++++++++++++++++++++--------------- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index 8bf44ab3..29d07784 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -34,12 +34,11 @@ class FileReceiver extends EventEmitter { const blob = new Blob([this.response]); const fileReader = new FileReader(); fileReader.onload = function() { + const meta = JSON.parse(xhr.getResponseHeader('X-File-Metadata')) resolve({ data: this.result, - aad: xhr.getResponseHeader('Additional-Data'), - fname: xhr - .getResponseHeader('Content-Disposition') - .match(/=(.+)/)[1] + aad: meta.aad, + filename: meta.filename }); }; @@ -78,7 +77,7 @@ class FileReceiver extends EventEmitter { fdata.data ), new Promise((resolve, reject) => { - resolve(fdata.fname); + resolve(fdata.filename); }) ]); }); diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index a4709d28..837dfbd0 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -75,9 +75,7 @@ class FileSender extends EventEmitter { const dataView = new DataView(encrypted); const blob = new Blob([dataView], { type: file.type }); const fd = new FormData(); - fd.append('fname', file.name); fd.append('data', blob, file.name); - fd.append('aad', arrayToHex(this.aad)); const xhr = new XMLHttpRequest(); @@ -102,6 +100,7 @@ class FileSender extends EventEmitter { }; xhr.open('post', '/upload/' + fileId, true); + xhr.setRequestHeader('X-File-Metadata', JSON.stringify({ aad: arrayToHex(this.aad), iv: fileId, filename: file.name })) xhr.send(fd); }); }) diff --git a/server/portal_server.js b/server/portal_server.js index c966e882..9685ac14 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -78,17 +78,15 @@ app.get('/assets/download/:id', (req, res) => { return; } - Promise.all([ - storage.filename(id), - storage.aad(id)]) - .then(([reply, aad]) => { + storage.metadata(id) + .then(meta => { storage.length(id).then(contentLength => { - + res.writeHead(200, { - 'Content-Disposition': 'attachment; filename=' + reply, + 'Content-Disposition': 'attachment; filename=' + meta.filename, 'Content-Type': 'application/octet-stream', 'Content-Length': contentLength, - 'Additional-Data': aad + 'X-File-Metadata': JSON.stringify(meta) }); const file_stream = storage.get(id); @@ -143,20 +141,20 @@ app.post('/upload/:id', (req, res, next) => { res.sendStatus(404); return; } - + const meta = JSON.parse(req.header('X-File-Metadata')); + log.info('meta', meta) req.pipe(req.busboy); - - req.busboy.on('field', (fieldname, value) => { - storage.setField(req.params.id, fieldname, value); - }) req.busboy.on('file', (fieldname, file, filename) => { log.info('Uploading:', req.params.id); - const protocol = conf.env === 'production' ? 'https' : req.protocol; - const url = `${protocol}://${req.get('host')}/download/${req.params.id}/`; - storage.set(req.params.id, file, filename, url).then(linkAndID => { - res.json(linkAndID); + storage.set(req.params.id, file, filename, meta).then(delete_token => { + const protocol = conf.env === 'production' ? 'https' : req.protocol; + const url = `${protocol}://${req.get('host')}/download/${req.params.id}/`; + res.json({ + url, + delete: delete_token + }); }); }); diff --git a/server/storage.js b/server/storage.js index f90d4f07..ce912186 100644 --- a/server/storage.js +++ b/server/storage.js @@ -31,7 +31,8 @@ if (conf.s3_bucket) { setField: setField, delete: awsDelete, forceDelete: awsForceDelete, - ping: awsPing + ping: awsPing, + metadata }; } else { module.exports = { @@ -44,10 +45,23 @@ if (conf.s3_bucket) { setField: setField, delete: localDelete, forceDelete: localForceDelete, - ping: localPing + ping: localPing, + metadata }; } +function metadata(id) { + return new Promise((resolve, reject) => { + redis_client.hgetall(id, (err, reply) => { + if (!err) { + resolve(reply); + } else { + reject(err); + } + }) + }) +} + function filename(id) { return new Promise((resolve, reject) => { redis_client.hget(id, 'filename', (err, reply) => { @@ -102,20 +116,16 @@ function localGet(id) { return fs.createReadStream(path.join(__dirname, '../static', id)); } -function localSet(id, file, filename, url) { +function localSet(id, file, filename, meta) { return new Promise((resolve, reject) => { const fstream = fs.createWriteStream(path.join(__dirname, '../static', id)); file.pipe(fstream); - fstream.on('close', () => { - const uuid = crypto.randomBytes(10).toString('hex'); - - redis_client.hmset([id, 'filename', filename, 'delete', uuid]); + fstream.on('close', () => { + meta.delete = crypto.randomBytes(10).toString('hex'); + redis_client.hmset(id, meta); redis_client.expire(id, 86400000); log.info('localSet:', 'Upload Finished of ' + id); - resolve({ - uuid: uuid, - url: url - }); + resolve(meta.delete); }); fstream.on('error', () => { @@ -183,7 +193,7 @@ function awsGet(id) { } } -function awsSet(id, file, filename, url) { +function awsSet(id, file, filename, meta) { const params = { Bucket: conf.s3_bucket, Key: id, @@ -196,16 +206,13 @@ function awsSet(id, file, filename, url) { log.info('awsUploadError:', err.stack); // an error occurred reject(); } else { - const uuid = crypto.randomBytes(10).toString('hex'); + meta.delete = crypto.randomBytes(10).toString('hex'); - redis_client.hmset([id, 'filename', filename, 'delete', uuid]); + redis_client.hmset(id, meta); redis_client.expire(id, 86400000); log.info('awsUploadFinish', 'Upload Finished of ' + filename); - resolve({ - uuid: uuid, - url: url - }); + resolve(meta.delete); } }); }); From 67f586b65cf957203bb4f6ab22a487b352fd56af Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Thu, 29 Jun 2017 10:30:08 -0700 Subject: [PATCH 05/12] format --- frontend/src/fileReceiver.js | 4 +-- frontend/src/fileSender.js | 49 +++++++++++++++++++++++------------- frontend/src/utils.js | 1 - server/log.js | 2 +- server/portal_server.js | 8 +++--- server/storage.js | 8 +++--- 6 files changed, 40 insertions(+), 32 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index 29d07784..db3f1515 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -1,8 +1,6 @@ const EventEmitter = require('events'); const { hexToArray } = require('./utils'); -const Raven = window.Raven; - class FileReceiver extends EventEmitter { constructor() { super(); @@ -34,7 +32,7 @@ class FileReceiver extends EventEmitter { const blob = new Blob([this.response]); const fileReader = new FileReader(); fileReader.onload = function() { - const meta = JSON.parse(xhr.getResponseHeader('X-File-Metadata')) + const meta = JSON.parse(xhr.getResponseHeader('X-File-Metadata')); resolve({ data: this.result, aad: meta.aad, diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index 837dfbd0..cbcbd76d 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -38,14 +38,18 @@ class FileSender extends EventEmitter { upload() { return Promise.all([ - window.crypto.subtle.generateKey( - { - name: 'AES-GCM', - length: 128 - }, - true, - ['encrypt', 'decrypt'] - ).catch(err => console.log('There was an error generating a crypto key')), + window.crypto.subtle + .generateKey( + { + name: 'AES-GCM', + length: 128 + }, + true, + ['encrypt', 'decrypt'] + ) + .catch(err => + console.log('There was an error generating a crypto key') + ), new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsArrayBuffer(this.file); @@ -56,15 +60,17 @@ class FileSender extends EventEmitter { ]) .then(([secretKey, plaintext]) => { return Promise.all([ - window.crypto.subtle.encrypt( - { - name: 'AES-GCM', - iv: this.iv, - additionalData: this.aad - }, - secretKey, - plaintext - ).catch(err => console.log('Error with encrypting.')), + window.crypto.subtle + .encrypt( + { + name: 'AES-GCM', + iv: this.iv, + additionalData: this.aad + }, + secretKey, + plaintext + ) + .catch(err => console.log('Error with encrypting.')), window.crypto.subtle.exportKey('jwk', secretKey) ]); }) @@ -100,7 +106,14 @@ class FileSender extends EventEmitter { }; xhr.open('post', '/upload/' + fileId, true); - xhr.setRequestHeader('X-File-Metadata', JSON.stringify({ aad: arrayToHex(this.aad), iv: fileId, filename: file.name })) + xhr.setRequestHeader( + 'X-File-Metadata', + JSON.stringify({ + aad: arrayToHex(this.aad), + iv: fileId, + filename: file.name + }) + ); xhr.send(fd); }); }) diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 39f058ca..2e6400ce 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -20,7 +20,6 @@ function hexToArray(str) { return iv; } - function notify(str) { if (!('Notification' in window)) { return; diff --git a/server/log.js b/server/log.js index 0042b6bc..27919e8d 100644 --- a/server/log.js +++ b/server/log.js @@ -1,6 +1,6 @@ const conf = require('./config.js'); -const isProduction = conf.env === 'production' +const isProduction = conf.env === 'production'; const mozlog = require('mozlog')({ app: 'FirefoxFileshare', diff --git a/server/portal_server.js b/server/portal_server.js index 9685ac14..8439675f 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -78,10 +78,10 @@ app.get('/assets/download/:id', (req, res) => { return; } - storage.metadata(id) + storage + .metadata(id) .then(meta => { storage.length(id).then(contentLength => { - res.writeHead(200, { 'Content-Disposition': 'attachment; filename=' + meta.filename, 'Content-Type': 'application/octet-stream', @@ -142,7 +142,7 @@ app.post('/upload/:id', (req, res, next) => { return; } const meta = JSON.parse(req.header('X-File-Metadata')); - log.info('meta', meta) + log.info('meta', meta); req.pipe(req.busboy); req.busboy.on('file', (fieldname, file, filename) => { @@ -157,8 +157,6 @@ app.post('/upload/:id', (req, res, next) => { }); }); }); - - }); app.get('/__lbheartbeat__', (req, res) => { diff --git a/server/storage.js b/server/storage.js index ce912186..2d37e163 100644 --- a/server/storage.js +++ b/server/storage.js @@ -58,8 +58,8 @@ function metadata(id) { } else { reject(err); } - }) - }) + }); + }); } function filename(id) { @@ -98,8 +98,8 @@ function aad(id) { } else { reject(); } - }) - }) + }); + }); } function localLength(id) { From a11b4b677c7882bcf653dcceb94be7694615f770 Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Thu, 29 Jun 2017 15:20:09 -0700 Subject: [PATCH 06/12] updated storage tests --- test/aws.storage.test.js | 9 ++++----- test/local.storage.test.js | 7 +++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/test/aws.storage.test.js b/test/aws.storage.test.js index 8dbb468a..61fe5657 100644 --- a/test/aws.storage.test.js +++ b/test/aws.storage.test.js @@ -112,11 +112,10 @@ describe('Testing Set using aws', function() { sinon.stub(crypto, 'randomBytes').returns(buf); s3Stub.upload.callsArgWith(1, null, {}); return storage - .set('123', {}, 'Filename.moz', 'url.com') - .then(reply => { - assert.equal(reply.uuid, buf.toString('hex')); - assert.equal(reply.url, 'url.com'); - assert.notEqual(reply.uuid, null); + .set('123', {}, 'Filename.moz', {}) + .then(deleteKey => { + assert.equal(deleteKey, buf.toString('hex')); + assert.notEqual(deleteKey, null); assert(expire.calledOnce); assert(expire.calledWith('123', 86400000)); }) diff --git a/test/local.storage.test.js b/test/local.storage.test.js index 659710a6..d965d8cc 100644 --- a/test/local.storage.test.js +++ b/test/local.storage.test.js @@ -122,10 +122,9 @@ describe('Testing Set to local filesystem', function() { fsStub.createWriteStream.returns({ on: stub }); return storage - .set('test', { pipe: sinon.stub() }, 'Filename.moz', 'moz.la') - .then(reply => { - assert(reply.uuid); - assert.equal(reply.url, 'moz.la'); + .set('test', { pipe: sinon.stub() }, 'Filename.moz', {}) + .then(deleteKey => { + assert(deleteKey); }) .catch(err => assert.fail()); }); From 1ce24f7e08ae1ae533536f3a37707fdfbe7d9333 Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Fri, 7 Jul 2017 14:47:56 -0700 Subject: [PATCH 07/12] id is now independent on iv --- frontend/src/fileReceiver.js | 7 +++---- server/portal_server.js | 10 +++++++--- server/storage.js | 21 ++++++++++++--------- test/aws.storage.test.js | 3 ++- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index db3f1515..274b0328 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -36,7 +36,8 @@ class FileReceiver extends EventEmitter { resolve({ data: this.result, aad: meta.aad, - filename: meta.filename + filename: meta.filename, + iv: meta.iv }); }; @@ -62,13 +63,11 @@ class FileReceiver extends EventEmitter { ['encrypt', 'decrypt'] ) ]).then(([fdata, key]) => { - const salt = this.salt; - return Promise.all([ window.crypto.subtle.decrypt( { name: 'AES-GCM', - iv: salt, + iv: hexToArray(fdata.iv), additionalData: hexToArray(fdata.aad) }, key, diff --git a/server/portal_server.js b/server/portal_server.js index 8439675f..50d4c732 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -137,7 +137,7 @@ app.post('/delete/:id', (req, res) => { }); app.post('/upload/:id', (req, res, next) => { - if (!validateID(req.params.id)) { + if (!validateIV(req.params.id)) { res.sendStatus(404); return; } @@ -148,9 +148,9 @@ app.post('/upload/:id', (req, res, next) => { req.busboy.on('file', (fieldname, file, filename) => { log.info('Uploading:', req.params.id); - storage.set(req.params.id, file, filename, meta).then(delete_token => { + storage.set(req.params.id, file, filename, meta).then(([delete_token, new_id]) => { const protocol = conf.env === 'production' ? 'https' : req.protocol; - const url = `${protocol}://${req.get('host')}/download/${req.params.id}/`; + const url = `${protocol}://${req.get('host')}/download/${new_id}/`; res.json({ url, delete: delete_token @@ -176,5 +176,9 @@ app.listen(conf.listen_port, () => { }); const validateID = route_id => { + return route_id.match(/^[0-9a-fA-F]{10}$/) !== null; +}; + +const validateIV = route_id => { return route_id.match(/^[0-9a-fA-F]{24}$/) !== null; }; diff --git a/server/storage.js b/server/storage.js index 2d37e163..ffa0a187 100644 --- a/server/storage.js +++ b/server/storage.js @@ -118,18 +118,20 @@ function localGet(id) { function localSet(id, file, filename, meta) { return new Promise((resolve, reject) => { - const fstream = fs.createWriteStream(path.join(__dirname, '../static', id)); + const new_id = crypto.randomBytes(5).toString('hex'); + const fstream = fs.createWriteStream(path.join(__dirname, '../static', new_id)); file.pipe(fstream); fstream.on('close', () => { meta.delete = crypto.randomBytes(10).toString('hex'); - redis_client.hmset(id, meta); + meta.id = id; + redis_client.hmset(new_id, meta); redis_client.expire(id, 86400000); - log.info('localSet:', 'Upload Finished of ' + id); - resolve(meta.delete); + log.info('localSet:', 'Upload Finished of ' + new_id); + resolve([meta.delete, new_id]); }); fstream.on('error', () => { - log.error('localSet:', 'Failed upload of ' + id); + log.error('localSet:', 'Failed upload of ' + new_id); reject(); }); }); @@ -194,9 +196,10 @@ function awsGet(id) { } function awsSet(id, file, filename, meta) { + const new_id = crypto.randomBytes(5).toString('hex'); const params = { Bucket: conf.s3_bucket, - Key: id, + Key: new_id, Body: file }; @@ -207,12 +210,12 @@ function awsSet(id, file, filename, meta) { reject(); } else { meta.delete = crypto.randomBytes(10).toString('hex'); - - redis_client.hmset(id, meta); + meta.id = id; + redis_client.hmset(new_id, meta); redis_client.expire(id, 86400000); log.info('awsUploadFinish', 'Upload Finished of ' + filename); - resolve(meta.delete); + resolve([meta.delete, new_id]); } }); }); diff --git a/test/aws.storage.test.js b/test/aws.storage.test.js index 61fe5657..dc19d5fc 100644 --- a/test/aws.storage.test.js +++ b/test/aws.storage.test.js @@ -113,8 +113,9 @@ describe('Testing Set using aws', function() { s3Stub.upload.callsArgWith(1, null, {}); return storage .set('123', {}, 'Filename.moz', {}) - .then(deleteKey => { + .then(([deleteKey, id]) => { assert.equal(deleteKey, buf.toString('hex')); + assert.notEqual(id, null); assert.notEqual(deleteKey, null); assert(expire.calledOnce); assert(expire.calledWith('123', 86400000)); From be470c6b6e3bb6879079bcf9d52444e6e45a964c Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Fri, 7 Jul 2017 14:59:42 -0700 Subject: [PATCH 08/12] added tagLength property to encrypt and decrypt for functionality in edge --- frontend/src/fileReceiver.js | 3 ++- frontend/src/fileSender.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index 274b0328..5e363140 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -68,7 +68,8 @@ class FileReceiver extends EventEmitter { { name: 'AES-GCM', iv: hexToArray(fdata.iv), - additionalData: hexToArray(fdata.aad) + additionalData: hexToArray(fdata.aad), + tagLength: 128 }, key, fdata.data diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index cbcbd76d..132b868c 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -65,7 +65,8 @@ class FileSender extends EventEmitter { { name: 'AES-GCM', iv: this.iv, - additionalData: this.aad + additionalData: this.aad, + tagLength: 128 }, secretKey, plaintext From dc4682eaf5606cb58cb0447bc9738e26f414561a Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Mon, 10 Jul 2017 11:25:03 -0700 Subject: [PATCH 09/12] added checksums --- frontend/src/fileReceiver.js | 27 ++++++++++++++++++++++++--- frontend/src/fileSender.js | 19 +++++++++++-------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index 5e363140..d6b8cc00 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -68,17 +68,38 @@ class FileReceiver extends EventEmitter { { name: 'AES-GCM', iv: hexToArray(fdata.iv), - additionalData: hexToArray(fdata.aad), - tagLength: 128 + additionalData: hexToArray(fdata.aad) }, key, fdata.data ), new Promise((resolve, reject) => { resolve(fdata.filename); + }), + new Promise((resolve, reject) => { + resolve(hexToArray(fdata.aad)); }) ]); - }); + }).then(([decrypted, fname, proposedHash]) => { + return window.crypto.subtle.digest('SHA-256', decrypted).then(calculatedHash => { + const integrity = new Uint8Array(calculatedHash).toString() === proposedHash.toString(); + if (!integrity) { + return new Promise((resolve, reject) => { + console.log('This file has been tampered with.') + reject(); + }) + } + + return Promise.all([ + new Promise((resolve, reject) => { + resolve(decrypted); + }), + new Promise((resolve, reject) => { + resolve(fname); + }) + ]); + }) + }) } } diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index 132b868c..ee433928 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -8,7 +8,6 @@ class FileSender extends EventEmitter { super(); this.file = file; this.iv = window.crypto.getRandomValues(new Uint8Array(12)); - this.aad = window.crypto.getRandomValues(new Uint8Array(6)); } static delete(fileId, token) { @@ -54,28 +53,32 @@ class FileSender extends EventEmitter { const reader = new FileReader(); reader.readAsArrayBuffer(this.file); reader.onload = function(event) { - resolve(new Uint8Array(this.result)); + const plaintext = new Uint8Array(this.result); + window.crypto.subtle.digest('SHA-256', plaintext).then(hash => { + resolve({plaintext: plaintext, hash: new Uint8Array(hash)}); + }) }; }) ]) - .then(([secretKey, plaintext]) => { + .then(([secretKey, file]) => { return Promise.all([ window.crypto.subtle .encrypt( { name: 'AES-GCM', iv: this.iv, - additionalData: this.aad, + additionalData: file.hash, tagLength: 128 }, secretKey, - plaintext + file.plaintext ) .catch(err => console.log('Error with encrypting.')), - window.crypto.subtle.exportKey('jwk', secretKey) + window.crypto.subtle.exportKey('jwk', secretKey), + new Promise((resolve, reject) => { resolve(file.hash) }) ]); }) - .then(([encrypted, keydata]) => { + .then(([encrypted, keydata, hash]) => { return new Promise((resolve, reject) => { const file = this.file; const fileId = arrayToHex(this.iv); @@ -110,7 +113,7 @@ class FileSender extends EventEmitter { xhr.setRequestHeader( 'X-File-Metadata', JSON.stringify({ - aad: arrayToHex(this.aad), + aad: arrayToHex(hash), iv: fileId, filename: file.name }) From 6f7930e34d15635eaf09aaac2bb53977bb4ce974 Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Mon, 10 Jul 2017 12:19:20 -0700 Subject: [PATCH 10/12] changed localstorage id's to match response from server, refactored meta.delete and newId out of storage module --- frontend/src/fileSender.js | 4 ++-- server/portal_server.js | 20 ++++++++++---------- server/storage.js | 24 ++++++++++-------------- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index ee433928..f2ed169d 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -102,14 +102,14 @@ class FileSender extends EventEmitter { const responseObj = JSON.parse(xhr.responseText); resolve({ url: responseObj.url, - fileId: fileId, + fileId: responseObj.id, secretKey: keydata.k, deleteToken: responseObj.uuid }); } }; - xhr.open('post', '/upload/' + fileId, true); + xhr.open('post', '/upload', true); xhr.setRequestHeader( 'X-File-Metadata', JSON.stringify({ diff --git a/server/portal_server.js b/server/portal_server.js index 50d4c732..4cb60008 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -8,6 +8,7 @@ const bytes = require('bytes'); const conf = require('./config.js'); const storage = require('./storage.js'); const Raven = require('raven'); +const crypto = require('crypto'); if (conf.sentry_dsn) { Raven.config(conf.sentry_dsn).install(); @@ -136,24 +137,23 @@ app.post('/delete/:id', (req, res) => { .catch(err => res.sendStatus(404)); }); -app.post('/upload/:id', (req, res, next) => { - if (!validateIV(req.params.id)) { - res.sendStatus(404); - return; - } - const meta = JSON.parse(req.header('X-File-Metadata')); +app.post('/upload', (req, res, next) => { + const newId = crypto.randomBytes(5).toString('hex'); + let meta = JSON.parse(req.header('X-File-Metadata')); + meta.delete = crypto.randomBytes(10).toString('hex'); log.info('meta', meta); req.pipe(req.busboy); req.busboy.on('file', (fieldname, file, filename) => { - log.info('Uploading:', req.params.id); + log.info('Uploading:', newId); - storage.set(req.params.id, file, filename, meta).then(([delete_token, new_id]) => { + storage.set(meta.iv, newId, file, filename, meta).then(() => { const protocol = conf.env === 'production' ? 'https' : req.protocol; - const url = `${protocol}://${req.get('host')}/download/${new_id}/`; + const url = `${protocol}://${req.get('host')}/download/${newId}/`; res.json({ url, - delete: delete_token + delete: meta.delete, + id: newId }); }); }); diff --git a/server/storage.js b/server/storage.js index ffa0a187..a4f9b673 100644 --- a/server/storage.js +++ b/server/storage.js @@ -116,22 +116,20 @@ function localGet(id) { return fs.createReadStream(path.join(__dirname, '../static', id)); } -function localSet(id, file, filename, meta) { +function localSet(id, newId, file, filename, meta) { return new Promise((resolve, reject) => { - const new_id = crypto.randomBytes(5).toString('hex'); - const fstream = fs.createWriteStream(path.join(__dirname, '../static', new_id)); + const fstream = fs.createWriteStream(path.join(__dirname, '../static', newId)); file.pipe(fstream); fstream.on('close', () => { - meta.delete = crypto.randomBytes(10).toString('hex'); meta.id = id; - redis_client.hmset(new_id, meta); + redis_client.hmset(newId, meta); redis_client.expire(id, 86400000); - log.info('localSet:', 'Upload Finished of ' + new_id); - resolve([meta.delete, new_id]); + log.info('localSet:', 'Upload Finished of ' + newId); + resolve(meta.delete); }); fstream.on('error', () => { - log.error('localSet:', 'Failed upload of ' + new_id); + log.error('localSet:', 'Failed upload of ' + newId); reject(); }); }); @@ -195,11 +193,10 @@ function awsGet(id) { } } -function awsSet(id, file, filename, meta) { - const new_id = crypto.randomBytes(5).toString('hex'); +function awsSet(id, newId, file, filename, meta) { const params = { Bucket: conf.s3_bucket, - Key: new_id, + Key: newId, Body: file }; @@ -209,13 +206,12 @@ function awsSet(id, file, filename, meta) { log.info('awsUploadError:', err.stack); // an error occurred reject(); } else { - meta.delete = crypto.randomBytes(10).toString('hex'); meta.id = id; - redis_client.hmset(new_id, meta); + redis_client.hmset(newId, meta); redis_client.expire(id, 86400000); log.info('awsUploadFinish', 'Upload Finished of ' + filename); - resolve([meta.delete, new_id]); + resolve(meta.delete); } }); }); From c4b7a2bd9757253dc77f9393f485ca8220457461 Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Mon, 10 Jul 2017 12:30:17 -0700 Subject: [PATCH 11/12] linting issues --- server/portal_server.js | 8 ++------ server/storage.js | 1 - test/aws.storage.test.js | 7 ++----- test/local.storage.test.js | 6 +++--- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/server/portal_server.js b/server/portal_server.js index 4cb60008..7bdebc1d 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -139,7 +139,7 @@ app.post('/delete/:id', (req, res) => { app.post('/upload', (req, res, next) => { const newId = crypto.randomBytes(5).toString('hex'); - let meta = JSON.parse(req.header('X-File-Metadata')); + const meta = JSON.parse(req.header('X-File-Metadata')); meta.delete = crypto.randomBytes(10).toString('hex'); log.info('meta', meta); req.pipe(req.busboy); @@ -177,8 +177,4 @@ app.listen(conf.listen_port, () => { const validateID = route_id => { return route_id.match(/^[0-9a-fA-F]{10}$/) !== null; -}; - -const validateIV = route_id => { - return route_id.match(/^[0-9a-fA-F]{24}$/) !== null; -}; +}; \ No newline at end of file diff --git a/server/storage.js b/server/storage.js index a4f9b673..e765b0c7 100644 --- a/server/storage.js +++ b/server/storage.js @@ -4,7 +4,6 @@ const s3 = new AWS.S3(); const conf = require('./config.js'); const fs = require('fs'); const path = require('path'); -const crypto = require('crypto'); const mozlog = require('./log.js'); diff --git a/test/aws.storage.test.js b/test/aws.storage.test.js index dc19d5fc..867c2009 100644 --- a/test/aws.storage.test.js +++ b/test/aws.storage.test.js @@ -112,11 +112,8 @@ describe('Testing Set using aws', function() { sinon.stub(crypto, 'randomBytes').returns(buf); s3Stub.upload.callsArgWith(1, null, {}); return storage - .set('123', {}, 'Filename.moz', {}) - .then(([deleteKey, id]) => { - assert.equal(deleteKey, buf.toString('hex')); - assert.notEqual(id, null); - assert.notEqual(deleteKey, null); + .set('123', '123', {}, 'Filename.moz', {}) + .then(() => { assert(expire.calledOnce); assert(expire.calledWith('123', 86400000)); }) diff --git a/test/local.storage.test.js b/test/local.storage.test.js index d965d8cc..022cf613 100644 --- a/test/local.storage.test.js +++ b/test/local.storage.test.js @@ -122,9 +122,9 @@ describe('Testing Set to local filesystem', function() { fsStub.createWriteStream.returns({ on: stub }); return storage - .set('test', { pipe: sinon.stub() }, 'Filename.moz', {}) - .then(deleteKey => { - assert(deleteKey); + .set('test', 'test', { pipe: sinon.stub() }, 'Filename.moz', {}) + .then(() => { + assert(1); }) .catch(err => assert.fail()); }); From 6aa79472bf2a26ecc566d18c3df7a6991414115d Mon Sep 17 00:00:00 2001 From: Abhinav Adduri Date: Mon, 10 Jul 2017 12:45:20 -0700 Subject: [PATCH 12/12] fixing small issues --- frontend/src/fileReceiver.js | 3 +-- frontend/src/fileSender.js | 5 ++--- server/portal_server.js | 2 +- server/storage.js | 10 ++++------ test/aws.storage.test.js | 2 +- test/local.storage.test.js | 2 +- 6 files changed, 10 insertions(+), 14 deletions(-) diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index d6b8cc00..37924038 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -4,7 +4,6 @@ const { hexToArray } = require('./utils'); class FileReceiver extends EventEmitter { constructor() { super(); - this.salt = hexToArray(location.pathname.slice(10, -1)); } download() { @@ -37,7 +36,7 @@ class FileReceiver extends EventEmitter { data: this.result, aad: meta.aad, filename: meta.filename, - iv: meta.iv + iv: meta.id }); }; diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index f2ed169d..5be5f490 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -72,8 +72,7 @@ class FileSender extends EventEmitter { }, secretKey, file.plaintext - ) - .catch(err => console.log('Error with encrypting.')), + ), window.crypto.subtle.exportKey('jwk', secretKey), new Promise((resolve, reject) => { resolve(file.hash) }) ]); @@ -114,7 +113,7 @@ class FileSender extends EventEmitter { 'X-File-Metadata', JSON.stringify({ aad: arrayToHex(hash), - iv: fileId, + id: fileId, filename: file.name }) ); diff --git a/server/portal_server.js b/server/portal_server.js index 7bdebc1d..c6ed936d 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -147,7 +147,7 @@ app.post('/upload', (req, res, next) => { req.busboy.on('file', (fieldname, file, filename) => { log.info('Uploading:', newId); - storage.set(meta.iv, newId, file, filename, meta).then(() => { + storage.set(newId, file, filename, meta).then(() => { const protocol = conf.env === 'production' ? 'https' : req.protocol; const url = `${protocol}://${req.get('host')}/download/${newId}/`; res.json({ diff --git a/server/storage.js b/server/storage.js index e765b0c7..38559ba3 100644 --- a/server/storage.js +++ b/server/storage.js @@ -115,14 +115,13 @@ function localGet(id) { return fs.createReadStream(path.join(__dirname, '../static', id)); } -function localSet(id, newId, file, filename, meta) { +function localSet(newId, file, filename, meta) { return new Promise((resolve, reject) => { const fstream = fs.createWriteStream(path.join(__dirname, '../static', newId)); file.pipe(fstream); fstream.on('close', () => { - meta.id = id; redis_client.hmset(newId, meta); - redis_client.expire(id, 86400000); + redis_client.expire(newId, 86400000); log.info('localSet:', 'Upload Finished of ' + newId); resolve(meta.delete); }); @@ -192,7 +191,7 @@ function awsGet(id) { } } -function awsSet(id, newId, file, filename, meta) { +function awsSet(newId, file, filename, meta) { const params = { Bucket: conf.s3_bucket, Key: newId, @@ -205,10 +204,9 @@ function awsSet(id, newId, file, filename, meta) { log.info('awsUploadError:', err.stack); // an error occurred reject(); } else { - meta.id = id; redis_client.hmset(newId, meta); - redis_client.expire(id, 86400000); + redis_client.expire(newId, 86400000); log.info('awsUploadFinish', 'Upload Finished of ' + filename); resolve(meta.delete); } diff --git a/test/aws.storage.test.js b/test/aws.storage.test.js index 867c2009..eef1f2a7 100644 --- a/test/aws.storage.test.js +++ b/test/aws.storage.test.js @@ -112,7 +112,7 @@ describe('Testing Set using aws', function() { sinon.stub(crypto, 'randomBytes').returns(buf); s3Stub.upload.callsArgWith(1, null, {}); return storage - .set('123', '123', {}, 'Filename.moz', {}) + .set('123', {}, 'Filename.moz', {}) .then(() => { assert(expire.calledOnce); assert(expire.calledWith('123', 86400000)); diff --git a/test/local.storage.test.js b/test/local.storage.test.js index 022cf613..3a9993b2 100644 --- a/test/local.storage.test.js +++ b/test/local.storage.test.js @@ -122,7 +122,7 @@ describe('Testing Set to local filesystem', function() { fsStub.createWriteStream.returns({ on: stub }); return storage - .set('test', 'test', { pipe: sinon.stub() }, 'Filename.moz', {}) + .set('test', { pipe: sinon.stub() }, 'Filename.moz', {}) .then(() => { assert(1); })