1
0
mirror of https://github.com/moparisthebest/mail synced 2024-12-22 15:28:49 -05:00

removed copied files from crypto lib

This commit is contained in:
Tankred Hase 2013-09-19 20:04:26 +02:00
parent 55abbc00cd
commit 9951a259a4
5 changed files with 7 additions and 803 deletions

8
.gitignore vendored
View File

@ -1,8 +1,12 @@
node_modules node_modules/
npm-debug.log npm-debug.log
.DS_Store .DS_Store
*-browserified.js *-browserified.js
test/new-unit/lib/ test/new-unit/lib/
.sass-cache .sass-cache
src/css/style.css
dist/ dist/
src/lib/*.js
src/js/crypto/aes-cbc.js
src/js/crypto/crypto-batch.js
src/js/crypto/rsa.js
src/js/crypto/util.js

View File

@ -1,91 +0,0 @@
(function() {
'use strict';
/**
* A Wrapper for Forge's AES-CBC encryption
*/
var AesCBC = function(forge) {
this._forge = forge;
};
/**
* Encrypt a String using AES-CBC-Pkcs7 using the provided keysize (e.g. 128, 256)
* @param plaintext [String] The input string in UTF-16
* @param key [String] The base64 encoded key
* @param iv [String] The base64 encoded IV
* @return [String] The base64 encoded ciphertext
*/
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 = 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 this._forge.util.encode64(cipher.output.getBytes());
};
/**
* Decrypt a String using AES-CBC-Pkcs7 using the provided keysize (e.g. 128, 256)
* @param ciphertext [String] The base64 encoded ciphertext
* @param key [String] The base64 encoded key
* @param iv [String] The base64 encoded IV
* @return [String] The decrypted plaintext in UTF-16
*/
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 = 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 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 || parts.length < 1 || !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) {
// AMD
define(['node-forge'], function(forge) {
return new AesCBC(forge);
});
} else if (typeof module !== 'undefined' && module.exports) {
// node.js
module.exports = new AesCBC(require('node-forge'));
}
})();

View File

@ -1,362 +0,0 @@
(function() {
'use strict';
/**
* Crypto batch library for processing large sets of data
*/
var CryptoBatch = function(aes, rsa, util, _) {
this._aes = aes;
this._rsa = rsa;
this._util = util;
this.__ = _;
};
//
// Encrypt batch for user AES/RSA
//
/**
* Encrypt and sign a list of items using AES and RSA
* @param list [Array] The list of items to encrypt
* @param receiverPubkeys [Array] A list of public keys used to encrypt
* @param senderPrivkey [Array] The sender's private key used to sign
*/
CryptoBatch.prototype.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) {
var receiverPk,
self = this;
// validate presence of args
if (!list || !receiverPubkeys || !senderPrivkey || !senderPrivkey._id || !senderPrivkey.privateKey) {
throw new Error('Arguments missing!');
}
// set sender private key
self._rsa.init(null, senderPrivkey.privateKey);
// encrypt a list of items
self.encryptList(list);
list.forEach(function(i) {
// fetch correct public key for encryption
receiverPk = null;
receiverPk = self.__.findWhere(receiverPubkeys, {
_id: i.receiverPk
});
// validate presence of args
if (!receiverPk || !receiverPk.publicKey || !i.key || !i.iv || !i.ciphertext) {
throw new Error('Arguments missing!');
}
// encrypt item for user
self.encryptItemKeyForUser(i, receiverPk.publicKey, senderPrivkey._id);
});
return list;
};
/**
* Encrypt and sign an item using AES and RSA
* @param i [Object] The item to encrypt
* @param receiverPubkey [String] The public key used to encrypt
* @param senderKeyId [String] The sender's private key ID used to sign
*/
CryptoBatch.prototype.encryptItemKeyForUser = function(i, receiverPubkey, senderKeyId) {
var self = this;
// set rsa public key used to encrypt
self._rsa.init(receiverPubkey);
// encrypt symmetric item key for user
i.encryptedKey = self._rsa.encrypt(i.key);
// set sender's keypair id for later verification
i.senderPk = senderKeyId;
// sign the bundle
i.signature = self._rsa.sign([i.iv, i.key, i.ciphertext]);
// delete plaintext values
delete i.key;
delete i.receiverPk;
return i;
};
//
// Decrypt batch for user AES/RSA
//
/**
* Decrypt and verify a list of items using AES and RSA
* @param list [Array] The list of items to decrypt
* @param senderPubkeys [Array] A list of public keys used to verify
* @param receiverPrivkey [Array] The receiver's private key used to decrypt
*/
CryptoBatch.prototype.decryptListForUser = function(list, senderPubkeys, receiverPrivkey) {
var j;
// validate presence of args
if (!list || !senderPubkeys || !receiverPrivkey || !receiverPrivkey._id || !receiverPrivkey.privateKey) {
throw new Error('Arguments missing!');
}
// verify and decrypt a list of items using RSA
this.decryptListKeysForUser(list, senderPubkeys, receiverPrivkey);
// decrypt a list of items
this.decryptList(list);
// set plaintext as list item
for (j = 0; j < list.length; j++) {
list[j] = list[j].plaintext;
}
return list;
};
/**
* Decrypt and verify a list of item keys using RSA
* @param list [Array] The list of items to decrypt
* @param senderPubkeys [Array] A list of public keys used to verify
* @param receiverPrivkey [String] The receiver's private key used to decrypt
*/
CryptoBatch.prototype.decryptListKeysForUser = function(list, senderPubkeys, receiverPrivkey) {
var self = this,
senderPk;
// set receiver private key
self._rsa.init(null, receiverPrivkey.privateKey);
list.forEach(function(i) {
// fetch correct public key for verification
senderPk = null;
senderPk = self.__.findWhere(senderPubkeys, {
_id: i.senderPk
});
// validate presence of args
if (!senderPk || !senderPk.publicKey || !i.encryptedKey || !i.iv || !i.ciphertext) {
throw new Error('Arguments missing!');
}
// decrypt item for user
self.decryptItemKeyForUser(i, senderPk.publicKey);
});
return list;
};
/**
* Verfiy an item and decrypt its item key using RSA
* @param i [Object] The item to decrypt
* @param senderPubkey [String] A public key used to verify
*/
CryptoBatch.prototype.decryptItemKeyForUser = function(i, senderPubkey) {
var self = this;
// set rsa public key used to verify
self._rsa.init(senderPubkey);
// decrypt symmetric item key for user
i.key = self._rsa.decrypt(i.encryptedKey);
// verify signature
if (!self._rsa.verify([i.iv, i.key, i.ciphertext], i.signature)) {
throw new Error('Verifying RSA signature failed!');
}
// delete ciphertext values
delete i.signature;
delete i.encryptedKey;
delete i.senderPk;
return i;
};
//
// Encrypt batch AES
//
/**
* Encrypt an item using AES
* @param i [Object] The item to encrypt
*/
CryptoBatch.prototype.encryptItem = function(i) {
var self = this;
// stringify to JSON before symmetric encryption
i.ciphertext = self._aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv);
// delete plaintext values
delete i.plaintext;
return i;
};
/**
* Encrypt a list of items using AES
* @param i [Object] The item to encrypt
*/
CryptoBatch.prototype.encryptList = function(list) {
var self = this;
list.forEach(function(i) {
// encrypt item
self.encryptItem(i);
});
return list;
};
/**
* Encrypt a list of items using AES and hash using HMAC
* @param i [Object] The item to encrypt
*/
CryptoBatch.prototype.authEncryptList = function(list) {
var self = this;
self.encryptList(list);
list.forEach(function(i) {
// calculate hmac of iv and ciphertext using key
i.hmac = self._aes.hmac([i.iv, i.ciphertext], i.key);
// delete symmetric key on each item
delete i.key;
});
return list;
};
//
// Decrypt batch AES
//
/**
* Decrypt an item using AES
* @param i [Object] The item to decrypt
*/
CryptoBatch.prototype.decryptItem = function(i) {
var self = this;
// symmetrically decrypt JSON and parse to object literal
i.plaintext = JSON.parse(self._aes.decrypt(i.ciphertext, i.key, i.iv));
// delete ciphertext values
delete i.ciphertext;
return i;
};
/**
* Decrypt a list of items using AES
* @param i [Object] The item to decrypt
*/
CryptoBatch.prototype.decryptList = function(list) {
var self = this;
list.forEach(function(i) {
// decrypt item
self.decryptItem(i);
});
return list;
};
/**
* Encrypt a list of items using AES and verfiy using HMAC
* @param i [Object] The item to decrypt
*/
CryptoBatch.prototype.authDecryptList = function(list, keys) {
var self = this,
i, len, calculated, j;
for (i = 0, len = list.length; i < len; i++) {
// validate presence of args
if (!list[i].hmac || !list[i].iv || !list[i].ciphertext || !keys[i]) {
throw new Error('Arguments for hmac verification missing!');
}
// verify hmac of each item
calculated = self._aes.hmac([list[i].iv, list[i].ciphertext], keys[i]);
if (list[i].hmac !== calculated) {
throw new Error('Hmac verification failed!');
}
// set key property for batch decryption
list[i].key = keys[i];
}
// decrypt lsit using aes
self.decryptList(list);
// set plaintext as list item
for (j = 0; j < list.length; j++) {
list[j] = list[j].plaintext;
}
return list;
};
//
// Reencrypt batch for user AES/RSA
//
/**
* Decrypt a list of item keys using RSA and the encrypt them again using AES
* @param list [Array] The list of items to decrypt
* @param senderPubkeys [Array] A list of public keys used to verify
* @param receiverPrivkey [String] The receiver's private key used to decrypt
* @param symKey [String] The symmetric key used to re-encrypt the item key
*/
CryptoBatch.prototype.reencryptListKeysForUser = function(list, senderPubkeys, receiverPrivkey, symKey) {
var self = this;
// verify and decrypt item keys using RSA
this.decryptListKeysForUser(list, senderPubkeys, receiverPrivkey);
list.forEach(function(i) {
// re-encrypt item key using aes
i.encryptedKey = self._aes.encrypt(i.key, symKey, i.iv);
delete i.key;
});
return list;
};
/**
* Decrypt keys and items using AES
* @param list [Array] The list of items to decrypt
* @param symKey [String] The symmetric key used to re-encrypt the item key
*/
CryptoBatch.prototype.decryptKeysAndList = function(list, symKey) {
var self = this,
j;
list.forEach(function(i) {
// decrypt item key
i.key = self._aes.decrypt(i.encryptedKey, symKey, i.iv);
// decrypt item for user
self.decryptItem(i);
delete i.encryptedKey;
});
// set plaintext as list item
for (j = 0; j < list.length; j++) {
list[j] = list[j].plaintext;
}
return list;
};
if (typeof define !== 'undefined' && define.amd) {
// AMD
define(['cryptoLib/aes-cbc', 'cryptoLib/rsa', 'cryptoLib/util', 'underscore'], function(aes, rsa, util, _) {
return new CryptoBatch(aes, rsa, util, _);
});
} else if (typeof module !== 'undefined' && module.exports) {
// node.js
module.exports = new CryptoBatch(require('./aes-cbc'), require('./rsa'), require('./util'), require('underscore'));
}
})();

View File

@ -1,140 +0,0 @@
(function() {
'use strict';
/**
* A Wrapper for Forge's RSA encryption
*/
var RSA = function(forge, util, app) {
var utl = forge.util;
var keypair = {};
/**
* Initializes the RSA module by passing the user's keypair
* The private key is option and required only for decryption
* and signing
*/
this.init = function(pubkeyPem, privkeyPem, keyId) {
if (pubkeyPem) {
keypair.publicKey = forge.pki.publicKeyFromPem(pubkeyPem);
}
if (privkeyPem) {
keypair.privateKey = forge.pki.privateKeyFromPem(privkeyPem);
}
if (keyId) {
keypair._id = keyId;
}
};
/**
* Generate RSA keypair with the corresponding keysize
*/
this.generateKeypair = function(keySize, callback) {
forge.rsa.generateKeyPair({
bits: keySize,
workerScript: (typeof app !== 'undefined') ? (app.config.workerPath + '/../lib/prime.worker.js') : undefined
}, function(err, newKeypair) {
if (err || !newKeypair || !newKeypair.publicKey || !newKeypair.privateKey) {
callback({
errMsg: 'RSA keygeneration failed!',
err: err
});
return;
}
keypair = newKeypair;
// generate unique keypair ID
keypair._id = util.UUID();
callback(null, {
_id: keypair._id,
pubkeyPem: forge.pki.publicKeyToPem(keypair.publicKey),
privkeyPem: forge.pki.privateKeyToPem(keypair.privateKey)
});
});
};
/**
* Exports user's keypair as PEMs
*/
this.exportKeys = function() {
return {
_id: keypair._id,
pubkeyPem: forge.pki.publicKeyToPem(keypair.publicKey),
privkeyPem: forge.pki.privateKeyToPem(keypair.privateKey)
};
};
/**
* Encrypt a String using RSA with PKCS#1 v1.5 padding
* @param plaintext [String] The input string in UTF-16
* @return [String] The base64 encoded ciphertext
*/
this.encrypt = function(plaintext) {
// encode plaintext to utf8 and encrypt
var ct = keypair.publicKey.encrypt(utl.encodeUtf8(plaintext));
// encode ciphtext to base64
return utl.encode64(ct);
};
/**
* Decrypt a String using RSA with PKCS#1 v1.5 padding
* @param ciphertext [String] The base64 encoded ciphertext
* @return [String] The decrypted plaintext in UTF-16
*/
this.decrypt = function(ciphertext) {
// decode base64 ciphertext to utf8
var ctUtf8 = utl.decode64(ciphertext);
// decrypt and decode to utf16
return utl.decodeUtf8(keypair.privateKey.decrypt(ctUtf8));
};
/**
* Signs an Array of Base64 encoded parts with the private key
* @param parts [Array] Array of Base64 encoded parts
* @return [String] The Base64 encoded signature
*/
this.sign = function(parts) {
var sha = forge.md.sha256.create();
parts.forEach(function(i) {
// decode base64 part and append to sha msg
sha.update(utl.decode64(i));
});
// encode signature to base64
return utl.encode64(keypair.privateKey.sign(sha));
};
/**
* Verifies an Array of Base64 encoded parts with the public key
* @param parts [Array] Array of Base64 encoded parts
* @param sig [String] The Base64 encoded signatrure
* @return [bool] if the verification was successful
*/
this.verify = function(parts, sig) {
// decode base64 signature to utf8
var sigUtf8 = utl.decode64(sig);
var sha = forge.md.sha256.create();
parts.forEach(function(i) {
// decode base64 part and append to sha msg
sha.update(utl.decode64(i));
});
return keypair.publicKey.verify(sha.digest().getBytes(), sigUtf8);
};
};
if (typeof define !== 'undefined' && define.amd) {
// AMD
define(['node-forge', 'cryptoLib/util', 'js/app-config'], function(forge, util, app) {
return new RSA(forge, util, app);
});
} else if (typeof module !== 'undefined' && module.exports) {
// node.js
module.exports = new RSA(require('node-forge'), require('./util'));
}
})();

View File

@ -1,207 +0,0 @@
(function() {
'use strict';
/**
* Various utitity methods for crypto, encoding & decoding
*/
var Util = function(forge, uuid, crypt) {
this._forge = forge;
this._uuid = uuid;
this._crypt = crypt;
};
/**
* Generates a new RFC 4122 version 4 compliant random UUID
*/
Util.prototype.UUID = function() {
return this._uuid.v4();
};
/**
* Generates a cryptographically secure random base64-encoded key or IV
* @param keySize [Number] The size of the key in bits (e.g. 128, 256)
* @return [String] The base64 encoded key/IV
*/
Util.prototype.random = function(keySize) {
var keyBase64, keyBuf;
if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
// browser if secure rng exists
keyBuf = new Uint8Array(keySize / 8);
window.crypto.getRandomValues(keyBuf);
keyBase64 = window.btoa(this.uint8Arr2BinStr(keyBuf));
} else if (typeof module !== 'undefined' && module.exports) {
// node.js
keyBuf = this._crypt.randomBytes(keySize / 8);
keyBase64 = new Buffer(keyBuf).toString('base64');
} else {
// generate random bytes with fortuna algorithm from forge
keyBase64 = window.btoa(this._forge.random.getBytesSync(keySize / 8));
}
return keyBase64;
};
/**
* Parse a date string with the following format "1900-01-31 18:17:53"
*/
Util.prototype.parseDate = function(str) {
var parts = str.match(/(\d+)/g);
return new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
};
/**
* Returns a string representation of a date in the format "1900-01-31 18:17:53"
*/
Util.prototype.formatDate = function(date) {
var year = "" + date.getFullYear();
var month = "" + (date.getMonth() + 1);
if (month.length === 1) {
month = "0" + month;
}
var day = "" + date.getDate();
if (day.length === 1) {
day = "0" + day;
}
var hour = "" + date.getHours();
if (hour.length === 1) {
hour = "0" + hour;
}
var minute = "" + date.getMinutes();
if (minute.length === 1) {
minute = "0" + minute;
}
var second = "" + date.getSeconds();
if (second.length === 1) {
second = "0" + second;
}
return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
};
/**
* Converts a binary String (e.g. from the FileReader Api) to an ArrayBuffer
* @param str [String] a binary string with integer values (0..255) per character
* @return [ArrayBuffer]
*/
Util.prototype.binStr2ArrBuf = function(str) {
var b = new ArrayBuffer(str.length);
var buf = new Uint8Array(b);
for (var i = 0, len = b.byteLength; i < len; i++) {
buf[i] = str.charCodeAt(i);
}
return b;
};
/**
* Converts an ArrayBuffer to a binary String. This is a slower alternative to
* conversion with arrBuf2Blob -> blob2BinStr, since these use native apis,
* but it can be used on browsers without the BlodBuilder Api
* @param buf [ArrayBuffer]
* @return [String] a binary string with integer values (0..255) per character
*/
Util.prototype.arrBuf2BinStr = function(buf) {
var b = new Uint8Array(buf);
var str = '';
for (var i = 0, len = b.length; i < len; i++) {
str += String.fromCharCode(b[i]);
}
return str;
};
/**
* Converts a UInt8Array to a binary String.
* @param buf [UInt8Array]
* @return [String] a binary string with integer values (0..255) per character
*/
Util.prototype.uint8Arr2BinStr = function(buf) {
var str = '';
for (var i = 0, len = buf.length; i < len; i++) {
str += String.fromCharCode(buf[i]);
}
return str;
};
/**
* Converts a binary String (e.g. from the FileReader Api) to a UInt8Array
* @param str [String] a binary string with integer values (0..255) per character
* @return [UInt8Array]
*/
Util.prototype.binStr2Uint8Arr = function(str) {
var c, buf = new Uint8Array(str.length);
for (var i = 0, len = buf.length; i < len; i++) {
c = str.charCodeAt(i);
buf[i] = (c & 0xff);
}
return buf;
};
/**
* Convert a str to base64 in a browser and in node.js
*/
Util.prototype.str2Base64 = function(str) {
if (typeof window !== 'undefined' && window.btoa) {
return window.btoa(str);
} else if (typeof module !== 'undefined' && module.exports) {
return new Buffer(str, 'binary').toString('base64');
} else {
return this._forge.util.encode64(str);
}
};
/**
* Convert a base64 encoded string in a browser and in node.js
*/
Util.prototype.base642Str = function(str) {
if (typeof window !== 'undefined' && window.atob) {
return window.atob(str);
} else if (typeof module !== 'undefined' && module.exports) {
return new Buffer(str, 'base64').toString('binary');
} else {
return this._forge.util.decode64(str);
}
};
/**
* Convert a UTF-16 encoded string to UTF8
* @param str [String] a UTF-16 encoded string
*/
Util.prototype.encodeUtf8 = function(str) {
return this._forge.util.encodeUtf8(str);
};
/**
* Convert a UTF-8 encoded string to UTF-16
* @param str [String] a UTF-8 encoded string
*/
Util.prototype.decodeUtf8 = function(str) {
return this._forge.util.decodeUtf8(str);
};
/**
* Validate an email address. This regex is taken from:
* http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
*/
Util.prototype.validateEmailAddress = function(emailAddress) {
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(emailAddress);
};
if (typeof define !== 'undefined' && define.amd) {
// AMD
define(['uuid', 'node-forge'], function(uuid, forge) {
return new Util(forge, uuid, undefined);
});
} else if (typeof module !== 'undefined' && module.exports) {
// node.js
module.exports = new Util(require('node-forge'), require('node-uuid'), require('crypto'));
}
})();