mirror of
https://github.com/moparisthebest/mail
synced 2025-02-26 15:51:44 -05:00
crypto error handling cleanup
This commit is contained in:
parent
d1290e7a9f
commit
628cb0ddd9
src/js
test/new-unit
@ -5,8 +5,8 @@
|
||||
* A Wrapper for Forge's AES-CBC encryption
|
||||
*/
|
||||
var AesCBC = function(forge) {
|
||||
|
||||
var utl = forge.util;
|
||||
this._forge = forge;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt a String using AES-CBC-Pkcs7 using the provided keysize (e.g. 128, 256)
|
||||
@ -15,20 +15,20 @@
|
||||
* @param iv [String] The base64 encoded IV
|
||||
* @return [String] The base64 encoded ciphertext
|
||||
*/
|
||||
this.encrypt = function(plaintext, key, iv) {
|
||||
AesCBC.prototype.encrypt = function(plaintext, key, iv) {
|
||||
// validate args
|
||||
if (!plaintext || !key || !iv) {
|
||||
throw new Error("Missing args for encryption!");
|
||||
}
|
||||
|
||||
// decode args to utf8 and encrypt
|
||||
var cipher = forge.aes.createEncryptionCipher(utl.decode64(key));
|
||||
cipher.start(utl.decode64(iv));
|
||||
cipher.update(utl.createBuffer(utl.encodeUtf8(plaintext)));
|
||||
var cipher = this._forge.aes.createEncryptionCipher(this._forge.util.decode64(key));
|
||||
cipher.start(this._forge.util.decode64(iv));
|
||||
cipher.update(this._forge.util.createBuffer(this._forge.util.encodeUtf8(plaintext)));
|
||||
cipher.finish();
|
||||
|
||||
// encode to base64
|
||||
return utl.encode64(cipher.output.getBytes());
|
||||
return this._forge.util.encode64(cipher.output.getBytes());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -38,22 +38,44 @@
|
||||
* @param iv [String] The base64 encoded IV
|
||||
* @return [String] The decrypted plaintext in UTF-16
|
||||
*/
|
||||
this.decrypt = function(ciphertext, key, iv) {
|
||||
AesCBC.prototype.decrypt = function(ciphertext, key, iv) {
|
||||
// validate args
|
||||
if (!ciphertext || !key || !iv) {
|
||||
throw new Error("Missing args for decryption!");
|
||||
}
|
||||
|
||||
// decode args input to utf8 decrypt
|
||||
var cipher = forge.aes.createDecryptionCipher(utl.decode64(key));
|
||||
cipher.start(utl.decode64(iv));
|
||||
cipher.update(utl.createBuffer(utl.decode64(ciphertext)));
|
||||
var cipher = this._forge.aes.createDecryptionCipher(this._forge.util.decode64(key));
|
||||
cipher.start(this._forge.util.decode64(iv));
|
||||
cipher.update(this._forge.util.createBuffer(this._forge.util.decode64(ciphertext)));
|
||||
cipher.finish();
|
||||
|
||||
// decode to utf16
|
||||
return utl.decodeUtf8(cipher.output.getBytes());
|
||||
return this._forge.util.decodeUtf8(cipher.output.getBytes());
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate a hmac using SHA-256 for a given input
|
||||
* @param parts [Array] Array of Base64 encoded parts
|
||||
* @param key [String] The base64 encoded key
|
||||
* @return [String] The Base64 encoded hmac
|
||||
*/
|
||||
AesCBC.prototype.hmac = function(parts, key) {
|
||||
var self = this;
|
||||
|
||||
// validate args
|
||||
if (!parts || !key) {
|
||||
throw new Error("Missing args for hmac processing!");
|
||||
}
|
||||
|
||||
var hmac = self._forge.hmac.create();
|
||||
hmac.start('sha256', self._forge.util.decode64(key));
|
||||
parts.forEach(function(i) {
|
||||
// decode base64 part and append to hmac msg
|
||||
hmac.update(self._forge.util.decode64(i));
|
||||
});
|
||||
|
||||
return self._forge.util.encode64(hmac.digest().getBytes());
|
||||
};
|
||||
|
||||
if (typeof define !== 'undefined' && define.amd) {
|
||||
|
@ -17,8 +17,27 @@
|
||||
|
||||
require(['cryptoLib/crypto-batch'], function(batch) {
|
||||
|
||||
var i = e.data,
|
||||
output = null;
|
||||
var output;
|
||||
|
||||
try {
|
||||
output = doOperation(batch, e.data);
|
||||
} catch (e) {
|
||||
output = {
|
||||
err: {
|
||||
errMsg: (e.message) ? e.message : e
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// pass output back to main thread
|
||||
self.postMessage(output);
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function doOperation(batch, i) {
|
||||
var output;
|
||||
|
||||
if (i.type === 'encrypt' && i.receiverPubkeys && i.senderPrivkey && i.list) {
|
||||
// start encryption
|
||||
@ -37,14 +56,14 @@
|
||||
output = batch.decryptKeysAndList(i.list, i.symKey);
|
||||
|
||||
} else {
|
||||
throw 'Not all arguments for web worker crypto are defined!';
|
||||
output = {
|
||||
err: {
|
||||
errMsg: 'Not all arguments for web worker crypto are defined!'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// pass output back to main thread
|
||||
self.postMessage(output);
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
return output;
|
||||
}
|
||||
|
||||
}());
|
@ -28,7 +28,7 @@
|
||||
// set sender's keypair id for later verification
|
||||
i.senderPk = senderKeyId;
|
||||
// sign the bundle
|
||||
i.signature = rsa.sign([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext]);
|
||||
i.signature = rsa.sign([i.iv, util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext]);
|
||||
|
||||
// delete plaintext values
|
||||
delete i.plaintext;
|
||||
@ -79,7 +79,7 @@
|
||||
rsa.init(senderPubkey);
|
||||
|
||||
// verify signature
|
||||
if (!rsa.verify([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext], i.signature)) {
|
||||
if (!rsa.verify([i.iv, util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext], i.signature)) {
|
||||
throw new Error('Verifying RSA signature failed!');
|
||||
}
|
||||
// decrypt symmetric item key for user
|
||||
|
@ -2,14 +2,18 @@
|
||||
* High level crypto api that invokes native crypto (if available) and
|
||||
* gracefully degrades to JS crypto (if unavailable)
|
||||
*/
|
||||
define(['cryptoLib/util', 'cryptoLib/aes-cbc', 'cryptoLib/rsa', 'cryptoLib/crypto-batch',
|
||||
'js/crypto/pbkdf2', 'js/app-config'
|
||||
], function(util, aes, rsa, cryptoBatch, pbkdf2, app) {
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var self = {};
|
||||
var util = require('cryptoLib/util'),
|
||||
aes = require('cryptoLib/aes-cbc'),
|
||||
rsa = require('cryptoLib/rsa'),
|
||||
cryptoBatch = require('cryptoLib/crypto-batch'),
|
||||
pbkdf2 = require('js/crypto/pbkdf2'),
|
||||
app = require('js/app-config');
|
||||
|
||||
var passBasedKey;
|
||||
var self = {},
|
||||
passBasedKey;
|
||||
|
||||
/**
|
||||
* Initializes the crypto modules by fetching the user's
|
||||
@ -288,7 +292,11 @@ define(['cryptoLib/util', 'cryptoLib/aes-cbc', 'cryptoLib/rsa', 'cryptoLib/crypt
|
||||
var worker = new Worker(app.config.workerPath + script);
|
||||
|
||||
worker.onmessage = function(e) {
|
||||
// return derived key from the worker
|
||||
if (e.data.err) {
|
||||
callback(e.data.err);
|
||||
return;
|
||||
}
|
||||
// return result from the worker
|
||||
callback(null, e.data);
|
||||
};
|
||||
|
||||
@ -297,7 +305,16 @@ define(['cryptoLib/util', 'cryptoLib/aes-cbc', 'cryptoLib/rsa', 'cryptoLib/crypt
|
||||
|
||||
} else {
|
||||
// no WebWorker support... do synchronous call
|
||||
var result = noWorker();
|
||||
var result;
|
||||
try {
|
||||
result = noWorker();
|
||||
} catch (e) {
|
||||
callback({
|
||||
errMsg: (e.message) ? e.message : e
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, result);
|
||||
}
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ define(function(require) {
|
||||
|
||||
/* message was not found in cache... fetch from imap server */
|
||||
|
||||
function messageReady(err, gottenMessage) {
|
||||
function bodyReady(err, gottenMessage) {
|
||||
message = gottenMessage;
|
||||
itemCounter++;
|
||||
// remember how many items should be fetched before the callback fires
|
||||
@ -311,10 +311,10 @@ define(function(require) {
|
||||
|
||||
// decrypt Message body
|
||||
if (message.body.indexOf(PREFIX) !== -1 && message.body.indexOf(SUFFIX) !== -1) {
|
||||
decryptMessageBody(message, function(err, ptMessage) {
|
||||
decryptBody(message, function(err, ptMessage) {
|
||||
message = ptMessage;
|
||||
// return decrypted message
|
||||
callback(null, message);
|
||||
callback(err, message);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -325,7 +325,7 @@ define(function(require) {
|
||||
//check();
|
||||
}
|
||||
|
||||
function decryptMessageBody(email, callback) {
|
||||
function decryptBody(email, callback) {
|
||||
var ctMessageBase64, ctMessage, pubkeyIds;
|
||||
|
||||
// parse email body for encrypted message block
|
||||
@ -390,7 +390,8 @@ define(function(require) {
|
||||
self._imapClient.getMessage({
|
||||
path: options.folder,
|
||||
uid: options.uid,
|
||||
onMessage: messageReady,
|
||||
onBody: bodyReady,
|
||||
onEnd: bodyReady
|
||||
/*onAttachment: attachmentReady*/
|
||||
});
|
||||
};
|
||||
|
@ -272,7 +272,7 @@ define(function(require) {
|
||||
it('should parse message body without attachement', function(done) {
|
||||
var uid = 415;
|
||||
|
||||
imapClientStub.getMessage.yieldsTo('onMessage', null, {
|
||||
imapClientStub.getMessage.yieldsTo('onBody', null, {
|
||||
uid: uid,
|
||||
body: ''
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user