added aad encryption
This commit is contained in:
parent
50995238bd
commit
34c367c49f
@ -1,5 +1,5 @@
|
|||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const { strToIv } = require('./utils');
|
const { strToIv, strToUintArr } = require('./utils');
|
||||||
|
|
||||||
const Raven = window.Raven;
|
const Raven = window.Raven;
|
||||||
|
|
||||||
@ -36,6 +36,7 @@ class FileReceiver extends EventEmitter {
|
|||||||
fileReader.onload = function() {
|
fileReader.onload = function() {
|
||||||
resolve({
|
resolve({
|
||||||
data: this.result,
|
data: this.result,
|
||||||
|
aad: xhr.getResponseHeader('Additional-Data'),
|
||||||
fname: xhr
|
fname: xhr
|
||||||
.getResponseHeader('Content-Disposition')
|
.getResponseHeader('Content-Disposition')
|
||||||
.match(/=(.+)/)[1]
|
.match(/=(.+)/)[1]
|
||||||
@ -65,12 +66,15 @@ class FileReceiver extends EventEmitter {
|
|||||||
)
|
)
|
||||||
]).then(([fdata, key]) => {
|
]).then(([fdata, key]) => {
|
||||||
const salt = this.salt;
|
const salt = this.salt;
|
||||||
|
console.log(strToUintArr(fdata.aad));
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
window.crypto.subtle.decrypt(
|
window.crypto.subtle.decrypt(
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
iv: salt,
|
iv: salt,
|
||||||
tagLength: 128
|
tagLength: 128,
|
||||||
|
additionalData: strToUintArr(fdata.aad)
|
||||||
},
|
},
|
||||||
key,
|
key,
|
||||||
fdata.data
|
fdata.data
|
||||||
|
@ -8,6 +8,7 @@ class FileSender extends EventEmitter {
|
|||||||
super();
|
super();
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.iv = window.crypto.getRandomValues(new Uint8Array(12));
|
this.iv = window.crypto.getRandomValues(new Uint8Array(12));
|
||||||
|
this.aad = window.crypto.getRandomValues(new Uint8Array(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
static delete(fileId, token) {
|
static delete(fileId, token) {
|
||||||
@ -60,7 +61,8 @@ class FileSender extends EventEmitter {
|
|||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
iv: this.iv,
|
iv: this.iv,
|
||||||
tagLength: 128
|
tagLength: 128,
|
||||||
|
additionalData: this.aad
|
||||||
},
|
},
|
||||||
secretKey,
|
secretKey,
|
||||||
plaintext
|
plaintext
|
||||||
@ -77,6 +79,7 @@ class FileSender extends EventEmitter {
|
|||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('fname', file.name);
|
fd.append('fname', file.name);
|
||||||
fd.append('data', blob, file.name);
|
fd.append('data', blob, file.name);
|
||||||
|
fd.append('aad', this.aad);
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ function strToIv(str) {
|
|||||||
return iv;
|
return iv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function notify(str) {
|
function notify(str) {
|
||||||
if (!('Notification' in window)) {
|
if (!('Notification' in window)) {
|
||||||
return;
|
return;
|
||||||
@ -32,8 +33,13 @@ function notify(str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function strToUintArr(str) {
|
||||||
|
return new Uint8Array(str.split(",").map(x => parseInt(x)));
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
ivToStr,
|
ivToStr,
|
||||||
strToIv,
|
strToIv,
|
||||||
notify
|
notify,
|
||||||
|
strToUintArr
|
||||||
};
|
};
|
||||||
|
@ -78,14 +78,17 @@ app.get('/assets/download/:id', (req, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
storage
|
Promise.all([
|
||||||
.filename(id)
|
storage.filename(id),
|
||||||
.then(reply => {
|
storage.aad(id)])
|
||||||
|
.then(([reply, aad]) => {
|
||||||
storage.length(id).then(contentLength => {
|
storage.length(id).then(contentLength => {
|
||||||
|
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Disposition': 'attachment; filename=' + reply,
|
'Content-Disposition': 'attachment; filename=' + reply,
|
||||||
'Content-Type': 'application/octet-stream',
|
'Content-Type': 'application/octet-stream',
|
||||||
'Content-Length': contentLength
|
'Content-Length': contentLength,
|
||||||
|
'Additional-Data': aad
|
||||||
});
|
});
|
||||||
const file_stream = storage.get(id);
|
const file_stream = storage.get(id);
|
||||||
|
|
||||||
@ -142,16 +145,22 @@ app.post('/upload/:id', (req, res, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.pipe(req.busboy);
|
req.pipe(req.busboy);
|
||||||
|
|
||||||
|
req.busboy.on('field', (fieldname, value) => {
|
||||||
|
storage.setField(req.params.id, fieldname, value);
|
||||||
|
})
|
||||||
|
|
||||||
req.busboy.on('file', (fieldname, file, filename) => {
|
req.busboy.on('file', (fieldname, file, filename) => {
|
||||||
log.info('Uploading:', req.params.id);
|
log.info('Uploading:', req.params.id);
|
||||||
|
|
||||||
const protocol = conf.env === 'production' ? 'https' : req.protocol;
|
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/${req.params.id}/`;
|
||||||
|
|
||||||
storage.set(req.params.id, file, filename, url).then(linkAndID => {
|
storage.set(req.params.id, file, filename, url).then(linkAndID => {
|
||||||
res.json(linkAndID);
|
res.json(linkAndID);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/__lbheartbeat__', (req, res) => {
|
app.get('/__lbheartbeat__', (req, res) => {
|
||||||
|
@ -27,6 +27,8 @@ if (conf.s3_bucket) {
|
|||||||
length: awsLength,
|
length: awsLength,
|
||||||
get: awsGet,
|
get: awsGet,
|
||||||
set: awsSet,
|
set: awsSet,
|
||||||
|
aad: aad,
|
||||||
|
setField: setField,
|
||||||
delete: awsDelete,
|
delete: awsDelete,
|
||||||
forceDelete: awsForceDelete,
|
forceDelete: awsForceDelete,
|
||||||
ping: awsPing
|
ping: awsPing
|
||||||
@ -38,6 +40,8 @@ if (conf.s3_bucket) {
|
|||||||
length: localLength,
|
length: localLength,
|
||||||
get: localGet,
|
get: localGet,
|
||||||
set: localSet,
|
set: localSet,
|
||||||
|
aad: aad,
|
||||||
|
setField: setField,
|
||||||
delete: localDelete,
|
delete: localDelete,
|
||||||
forceDelete: localForceDelete,
|
forceDelete: localForceDelete,
|
||||||
ping: localPing
|
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) {
|
function localLength(id) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
@ -86,7 +106,7 @@ function localSet(id, file, filename, url) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const fstream = fs.createWriteStream(path.join(__dirname, '../static', id));
|
const fstream = fs.createWriteStream(path.join(__dirname, '../static', id));
|
||||||
file.pipe(fstream);
|
file.pipe(fstream);
|
||||||
fstream.on('close', () => {
|
fstream.on('close', () => {
|
||||||
const uuid = crypto.randomBytes(10).toString('hex');
|
const uuid = crypto.randomBytes(10).toString('hex');
|
||||||
|
|
||||||
redis_client.hmset([id, 'filename', filename, 'delete', uuid]);
|
redis_client.hmset([id, 'filename', filename, 'delete', uuid]);
|
||||||
|
Loading…
Reference in New Issue
Block a user