diff --git a/src/js/crypto/aes-batch-worker.js b/src/js/crypto/aes-batch-worker.js index e6f21cb..81b0a16 100644 --- a/src/js/crypto/aes-batch-worker.js +++ b/src/js/crypto/aes-batch-worker.js @@ -15,8 +15,8 @@ var i = e.data, output = null, - aes = new app.crypto.AesCBC(forge), - batch = new app.crypto.CryptoBatch(aes); + aes = new cryptoLib.AesCBC(forge), + batch = new cryptoLib.CryptoBatch(aes); if (i.type === 'encrypt' && i.list) { // start encryption diff --git a/src/js/crypto/aes-cbc.js b/src/js/crypto/aes-cbc.js index e297a5c..7866338 100644 --- a/src/js/crypto/aes-cbc.js +++ b/src/js/crypto/aes-cbc.js @@ -1,51 +1,57 @@ -/** - * A Wrapper for Forge's AES-CBC encryption - */ -var AesCBC = function(forge) { +(function() { 'use strict'; - var utl = forge.util; - /** - * 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 + * A Wrapper for Forge's AES-CBC encryption */ - this.encrypt = function(plaintext, key, iv) { - // 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))); - cipher.finish(); + var AesCBC = function(forge) { + + var utl = forge.util; + + /** + * 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 + */ + this.encrypt = function(plaintext, key, iv) { + // 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))); + cipher.finish(); + + // encode to base64 + return utl.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 + */ + this.decrypt = function(ciphertext, key, iv) { + // 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))); + cipher.finish(); + + // decode to utf16 + return utl.decodeUtf8(cipher.output.getBytes()); + }; - // encode to base64 - return utl.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 - */ - this.decrypt = function(ciphertext, key, iv) { - // 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))); - cipher.finish(); + if (typeof module !== 'undefined' && module.exports) { + module.exports = AesCBC; + } else { + var that = (typeof window !== 'undefined') ? window : self; + that.cryptoLib = that.cryptoLib || {}; + that.cryptoLib.AesCBC = AesCBC; + } - // decode to utf16 - return utl.decodeUtf8(cipher.output.getBytes()); - }; - -}; - -if (typeof module !== 'undefined' && module.exports) { - module.exports = AesCBC; -} else { - app.crypto.AesCBC = AesCBC; -} \ No newline at end of file +})(); \ No newline at end of file diff --git a/src/js/crypto/aes-worker.js b/src/js/crypto/aes-worker.js index 8551618..eee4597 100644 --- a/src/js/crypto/aes-worker.js +++ b/src/js/crypto/aes-worker.js @@ -14,7 +14,7 @@ var i = e.data, output = null, - aes = new app.crypto.AesCBC(forge); + aes = new cryptoLib.AesCBC(forge); if (i.type === 'encrypt' && i.plaintext && i.key && i.iv) { // start encryption diff --git a/src/js/crypto/crypto-batch-worker.js b/src/js/crypto/crypto-batch-worker.js index 57650b3..914c154 100644 --- a/src/js/crypto/crypto-batch-worker.js +++ b/src/js/crypto/crypto-batch-worker.js @@ -17,10 +17,10 @@ var i = e.data, output = null, - aes = new app.crypto.AesCBC(forge), - rsa = new app.crypto.RSA(forge), - util = new app.crypto.Util(), - batch = new app.crypto.CryptoBatch(aes, rsa, util); + aes = new cryptoLib.AesCBC(forge), + rsa = new cryptoLib.RSA(forge), + util = new cryptoLib.Util(), + batch = new cryptoLib.CryptoBatch(aes, rsa, util); // pass RSA keys to module rsa.init(i.pubkeyPem, i.privkeyPem); diff --git a/src/js/crypto/crypto-batch.js b/src/js/crypto/crypto-batch.js index 49a1411..6a38e95 100644 --- a/src/js/crypto/crypto-batch.js +++ b/src/js/crypto/crypto-batch.js @@ -1,91 +1,97 @@ -/** - * Crypto batch library for processing large sets of data - */ -var CryptoBatch = function(aes, rsa, util) { +(function() { 'use strict'; /** - * Encrypt a list of items using AES - * @list list [Array] The list of items to encrypt + * Crypto batch library for processing large sets of data */ - this.encryptList = function(list) { - list.forEach(function(i) { - // stringify to JSON before encryption - i.ciphertext = aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv); - delete i.plaintext; - }); + var CryptoBatch = function(aes, rsa, util) { - return list; - }; + /** + * Encrypt a list of items using AES + * @list list [Array] The list of items to encrypt + */ + this.encryptList = function(list) { + list.forEach(function(i) { + // stringify to JSON before encryption + i.ciphertext = aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv); + delete i.plaintext; + }); - /** - * Decrypt a list of items using AES - * @list list [Array] The list of items to decrypt - */ - this.decryptList = function(list) { - list.forEach(function(i) { - // decrypt JSON and parse to object literal - i.plaintext = JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv)); - delete i.ciphertext; - }); + return list; + }; - return list; - }; + /** + * Decrypt a list of items using AES + * @list list [Array] The list of items to decrypt + */ + this.decryptList = function(list) { + list.forEach(function(i) { + // decrypt JSON and parse to object literal + i.plaintext = JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv)); + delete i.ciphertext; + }); - /** - * Encrypt and sign a list of items using AES and RSA - * @list list [Array] The list of items to encrypt - */ - this.encryptListForUser = function(list) { - // encrypt list - var encryptedList = this.encryptList(list); + return list; + }; - // encrypt keys for user - encryptedList.forEach(function(i) { - // process new values - i.encryptedKey = rsa.encrypt(i.key); - i.signature = rsa.sign([i.iv, util.str2Base64(i.id), i.encryptedKey, i.ciphertext]); - // delete old ones - delete i.key; - }); + /** + * Encrypt and sign a list of items using AES and RSA + * @list list [Array] The list of items to encrypt + */ + this.encryptListForUser = function(list) { + // encrypt list + var encryptedList = this.encryptList(list); - return encryptedList; - }; + // encrypt keys for user + encryptedList.forEach(function(i) { + // process new values + i.encryptedKey = rsa.encrypt(i.key); + i.signature = rsa.sign([i.iv, util.str2Base64(i.id), i.encryptedKey, i.ciphertext]); + // delete old ones + delete i.key; + }); - /** - * Decrypt and verify a list of items using AES and RSA - * @list list [Array] The list of items to decrypt - */ - this.decryptListForUser = function(encryptedList) { - var j, self = this; + return encryptedList; + }; - // decrypt keys for user - encryptedList.forEach(function(i) { - // verify signature - if (!rsa.verify([i.iv, util.str2Base64(i.id), i.encryptedKey, i.ciphertext], i.signature)) { - throw new Error('Verifying RSA signature failed!'); + /** + * Decrypt and verify a list of items using AES and RSA + * @list list [Array] The list of items to decrypt + */ + this.decryptListForUser = function(encryptedList) { + var j, self = this; + + // decrypt keys for user + encryptedList.forEach(function(i) { + // verify signature + if (!rsa.verify([i.iv, util.str2Base64(i.id), i.encryptedKey, i.ciphertext], i.signature)) { + throw new Error('Verifying RSA signature failed!'); + } + // precoess new values + i.key = rsa.decrypt(i.encryptedKey); + // delete old values + delete i.signature; + delete i.encryptedKey; + }); + + // decrypt list + var decryptedList = this.decryptList(encryptedList); + + // add plaintext to list + for (j = 0; j < decryptedList.length; j++) { + decryptedList[j] = decryptedList[j].plaintext; } - // precoess new values - i.key = rsa.decrypt(i.encryptedKey); - // delete old values - delete i.signature; - delete i.encryptedKey; - }); - // decrypt list - var decryptedList = this.decryptList(encryptedList); - - // add plaintext to list - for (j = 0; j < decryptedList.length; j++) { - decryptedList[j] = decryptedList[j].plaintext; - } - - return decryptedList; + return decryptedList; + }; }; -}; -if (typeof module !== 'undefined' && module.exports) { - module.exports = CryptoBatch; -} else { - app.crypto.CryptoBatch = CryptoBatch; -} \ No newline at end of file + if (typeof module !== 'undefined' && module.exports) { + module.exports = CryptoBatch; + } else { + var that = (typeof window !== 'undefined') ? window : self; + that.cryptoLib = that.cryptoLib || {}; + that.cryptoLib.CryptoBatch = CryptoBatch; + } + +})(); \ No newline at end of file diff --git a/src/js/crypto/crypto.js b/src/js/crypto/crypto.js index 7cab0ec..f59e4de 100644 --- a/src/js/crypto/crypto.js +++ b/src/js/crypto/crypto.js @@ -5,8 +5,8 @@ app.crypto.Crypto = function(window, util) { 'use strict'; - var aes = new app.crypto.AesCBC(forge); // use AES-CBC mode by default - var rsa = new app.crypto.RSA(forge, util); // use RSA for asym. crypto + var aes = new cryptoLib.AesCBC(forge); // use AES-CBC mode by default + var rsa = new cryptoLib.RSA(forge, util); // use RSA for asym. crypto var keyStore = new app.dao.LocalStorageDAO(window); var storageId; // storage id for the encrypted keypair in local storage @@ -232,7 +232,7 @@ app.crypto.Crypto = function(window, util) { }); } else { - var batch = new app.crypto.CryptoBatch(aes); + var batch = new cryptoLib.CryptoBatch(aes); var encryptedList = batch.encryptList(list); callback(encryptedList); } @@ -251,7 +251,7 @@ app.crypto.Crypto = function(window, util) { }); } else { - var batch = new app.crypto.CryptoBatch(aes); + var batch = new cryptoLib.CryptoBatch(aes); var decryptedList = batch.decryptList(list); callback(decryptedList); } @@ -292,7 +292,7 @@ app.crypto.Crypto = function(window, util) { }); } else { - var batch = new app.crypto.CryptoBatch(aes, rsa, util); + var batch = new cryptoLib.CryptoBatch(aes, rsa, util); var encryptedList = batch.encryptListForUser(envelopes); callback(null, encryptedList); } @@ -315,7 +315,7 @@ app.crypto.Crypto = function(window, util) { }); } else { - var batch = new app.crypto.CryptoBatch(aes, rsa, util); + var batch = new cryptoLib.CryptoBatch(aes, rsa, util); var decryptedList = batch.decryptListForUser(list); callback(null, decryptedList); } diff --git a/src/js/crypto/rsa.js b/src/js/crypto/rsa.js index a48cc90..ba67a14 100644 --- a/src/js/crypto/rsa.js +++ b/src/js/crypto/rsa.js @@ -1,132 +1,138 @@ -/** - * A Wrapper for Forge's RSA encryption - */ -var RSA = function(forge, util) { +(function() { 'use strict'; - 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 + * A Wrapper for Forge's RSA encryption */ - 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; - } - }; + var RSA = function(forge, util) { - /** - * 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/forge/prime.worker.js') : undefined - }, function(err, newKeypair) { - if (err || !newKeypair || !newKeypair.publicKey || !newKeypair.privateKey) { - callback({ - errMsg: 'RSA keygeneration failed!', - err: err - }); - return; + 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; + } + }; - keypair = newKeypair; - // generate unique keypair ID - keypair._id = util.UUID(); + /** + * 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/forge/prime.worker.js') : undefined + }, function(err, newKeypair) { + if (err || !newKeypair || !newKeypair.publicKey || !newKeypair.privateKey) { + callback({ + errMsg: 'RSA keygeneration failed!', + err: err + }); + return; + } - callback(null, { + 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) - }); - }); - }; - - /** - * 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); + }; + }; - /** - * 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); - }; + if (typeof module !== 'undefined' && module.exports) { + module.exports = RSA; + } else { + var that = (typeof window !== 'undefined') ? window : self; + that.cryptoLib = that.cryptoLib || {}; + that.cryptoLib.RSA = RSA; + } - /** - * 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 module !== 'undefined' && module.exports) { - module.exports = RSA; -} else { - app.crypto.RSA = RSA; -} \ No newline at end of file +})(); \ No newline at end of file diff --git a/src/js/crypto/util.js b/src/js/crypto/util.js index ec24cab..f9d454c 100644 --- a/src/js/crypto/util.js +++ b/src/js/crypto/util.js @@ -1,203 +1,209 @@ -/** - * Various utitity methods for crypto, encoding & decoding - */ -var Util = function(window, uuid, crypt) { +(function() { 'use strict'; /** - * Generates a new RFC 4122 version 4 compliant random UUID + * Various utitity methods for crypto, encoding & decoding */ - this.UUID = function() { - return uuid.v4(); - }; + var Util = function(window, uuid, crypt) { - /** - * 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 - */ - this.random = function(keySize) { - var keyBase64, keyBuf; - - if (typeof module !== 'undefined' && module.exports) { - // node.js - keyBuf = crypt.randomBytes(keySize / 8); - keyBase64 = new Buffer(keyBuf).toString('base64'); - - } else if (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 { - // generate random bytes with fortuna algorithm from forge - keyBase64 = window.btoa(forge.random.getBytesSync(keySize / 8)); - } - - return keyBase64; - }; - - /** - * Parse a date string with the following format "1900-01-31 18:17:53" - */ - this.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" - */ - this.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] - */ - this.binStr2ArrBuf = function(str) { - var b = new ArrayBuffer(str.length); - var buf = new Uint8Array(b); - - for (var i = 0; i < b.byteLength; i++) { - buf[i] = str.charCodeAt(i); - } - - return b; - }; - - /** - * Creates a Blob from an ArrayBuffer using the BlobBuilder Api - * @param str [String] a binary string with integer values (0..255) per character - * @return [ArrayBuffer] either a data url or a filesystem url - */ - this.arrBuf2Blob = function(buf, mimeType) { - var b = new Uint8Array(buf); - var blob = new Blob([b], { - type: mimeType - }); - - return blob; - }; - - /** - * Creates a binary String from a Blob using the FileReader Api - * @param blob [Blob/File] a blob containing the the binary data - * @return [String] a binary string with integer values (0..255) per character - */ - this.blob2BinStr = function(blob, callback) { - var reader = new FileReader(); - - reader.onload = function(event) { - callback(event.target.result); + /** + * Generates a new RFC 4122 version 4 compliant random UUID + */ + this.UUID = function() { + return 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 + */ + this.random = function(keySize) { + var keyBase64, keyBuf; + + if (typeof module !== 'undefined' && module.exports) { + // node.js + keyBuf = crypt.randomBytes(keySize / 8); + keyBase64 = new Buffer(keyBuf).toString('base64'); + + } else if (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 { + // generate random bytes with fortuna algorithm from forge + keyBase64 = window.btoa(forge.random.getBytesSync(keySize / 8)); + } + + return keyBase64; + }; + + /** + * Parse a date string with the following format "1900-01-31 18:17:53" + */ + this.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" + */ + this.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] + */ + this.binStr2ArrBuf = function(str) { + var b = new ArrayBuffer(str.length); + var buf = new Uint8Array(b); + + for (var i = 0; i < b.byteLength; i++) { + buf[i] = str.charCodeAt(i); + } + + return b; + }; + + /** + * Creates a Blob from an ArrayBuffer using the BlobBuilder Api + * @param str [String] a binary string with integer values (0..255) per character + * @return [ArrayBuffer] either a data url or a filesystem url + */ + this.arrBuf2Blob = function(buf, mimeType) { + var b = new Uint8Array(buf); + var blob = new Blob([b], { + type: mimeType + }); + + return blob; + }; + + /** + * Creates a binary String from a Blob using the FileReader Api + * @param blob [Blob/File] a blob containing the the binary data + * @return [String] a binary string with integer values (0..255) per character + */ + this.blob2BinStr = function(blob, callback) { + var reader = new FileReader(); + + reader.onload = function(event) { + callback(event.target.result); + }; + + reader.readAsBinaryString(blob); + }; + + /** + * 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 + */ + this.arrBuf2BinStr = function(buf) { + var b = new Uint8Array(buf); + var str = ''; + + for (var i = 0; i < b.length; 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 + */ + this.uint8Arr2BinStr = function(buf) { + var str = ''; + + for (var i = 0; i < buf.length; 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] + */ + this.binStr2Uint8Arr = function(str) { + var c, buf = new Uint8Array(str.length); + + for (var i = 0; i < buf.length; i++) { + c = str.charCodeAt(i); + buf[i] = (c & 0xff); + } + + return buf; + }; + + /** + * Convert a str to base64 in a browser and in node.js + */ + this.str2Base64 = function(str) { + if (typeof module !== 'undefined' && module.exports) { + return new Buffer(str, 'binary').toString('base64'); + } else if (typeof window !== 'undefined' && window.btoa) { + return window.btoa(str); + } else { + return forge.util.encode64(str); + } + }; + + /** + * Convert a base64 encoded string in a browser and in node.js + */ + this.base642Str = function(str) { + if (typeof module !== 'undefined' && module.exports) { + return new Buffer(str, 'base64').toString('binary'); + } else if (typeof window !== 'undefined' && window.atob) { + return window.atob(str); + } else { + return forge.util.decode64(str); + } }; - reader.readAsBinaryString(blob); }; - /** - * 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 - */ - this.arrBuf2BinStr = function(buf) { - var b = new Uint8Array(buf); - var str = ''; + if (typeof module !== 'undefined' && module.exports) { + module.exports = Util; + } else { + var that = (typeof window !== 'undefined') ? window : self; + that.cryptoLib = that.cryptoLib || {}; + that.cryptoLib.Util = Util; + } - for (var i = 0; i < b.length; 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 - */ - this.uint8Arr2BinStr = function(buf) { - var str = ''; - - for (var i = 0; i < buf.length; 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] - */ - this.binStr2Uint8Arr = function(str) { - var c, buf = new Uint8Array(str.length); - - for (var i = 0; i < buf.length; i++) { - c = str.charCodeAt(i); - buf[i] = (c & 0xff); - } - - return buf; - }; - - /** - * Convert a str to base64 in a browser and in node.js - */ - this.str2Base64 = function(str) { - if (typeof module !== 'undefined' && module.exports) { - return new Buffer(str, 'binary').toString('base64'); - } else if (typeof window !== 'undefined' && window.btoa) { - return window.btoa(str); - } else { - return forge.util.encode64(str); - } - }; - - /** - * Convert a base64 encoded string in a browser and in node.js - */ - this.base642Str = function(str) { - if (typeof module !== 'undefined' && module.exports) { - return new Buffer(str, 'base64').toString('binary'); - } else if (typeof window !== 'undefined' && window.atob) { - return window.atob(str); - } else { - return forge.util.decode64(str); - } - }; - -}; - -if (typeof module !== 'undefined' && module.exports) { - module.exports = Util; -} else { - app.crypto.Util = Util; -} \ No newline at end of file +})(); \ No newline at end of file diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index e326561..94ad0a3 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -15,7 +15,7 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, util) { var storedKey = crypto.getEncryptedPrivateKey(account.get('emailAddress')); cloudstorage.syncPrivateKey(account.get('emailAddress'), storedKey, function(err) { if (err) { - console.log('Error syncing secret key to cloud: ' + err); + console.log('Error syncing private key to cloud: ' + err); } // init crypto initCrypto(); diff --git a/test/test-data.js b/test/test-data.js index 8bec276..5e1f845 100644 --- a/test/test-data.js +++ b/test/test-data.js @@ -1,6 +1,6 @@ var TestData = function() { - var util = new app.crypto.Util(window, uuid); + var util = new cryptoLib.Util(window, uuid); this.getEmailCollection = function(size) { // create test data diff --git a/test/unit/aes-test.js b/test/unit/aes-test.js index bf4609d..7247edc 100644 --- a/test/unit/aes-test.js +++ b/test/unit/aes-test.js @@ -2,12 +2,12 @@ module("AES Crypto"); var aes_test = { keySize: 128, - util: new app.crypto.Util(window, uuid), + util: new cryptoLib.Util(window, uuid), test_message: new TestData().generateBigString(1000) }; test("CBC mode", 4, function() { - var aes = new app.crypto.AesCBC(forge); + var aes = new cryptoLib.AesCBC(forge); var plaintext = aes_test.test_message; var key = aes_test.util.random(aes_test.keySize); @@ -20,18 +20,4 @@ test("CBC mode", 4, function() { var decrypted = aes.decrypt(ciphertext, key, iv); equal(decrypted, plaintext, 'Decryption correct' + decrypted); -}); - -// test("CCM mode", 2, function() { -// var aes = new app.crypto.AesCCM(sjcl); - -// var plaintext = aes_test.test_message; -// var key = aes_test.util.random(aes_test.keySize); -// var iv = aes_test.util.random(104); - -// var ciphertext = aes.encrypt(plaintext, key, iv); -// ok(ciphertext, 'Ciphertext length: ' + ciphertext.length); - -// var decrypted = aes.decrypt(ciphertext, key, iv); -// equal(decrypted, plaintext, 'Decryption correct: ' + decrypted); -// }); \ No newline at end of file +}); \ No newline at end of file diff --git a/test/unit/crypto-test.js b/test/unit/crypto-test.js index 8f83026..dc8cfcb 100644 --- a/test/unit/crypto-test.js +++ b/test/unit/crypto-test.js @@ -10,7 +10,7 @@ var crypto_test = { asyncTest("Init", 2, function() { // init dependencies - crypto_test.util = new app.crypto.Util(window, uuid); + crypto_test.util = new cryptoLib.Util(window, uuid); crypto_test.crypto = new app.crypto.Crypto(window, crypto_test.util); ok(crypto_test.crypto, 'Crypto'); diff --git a/test/unit/devicestorage-test.js b/test/unit/devicestorage-test.js index ef7496c..4cc664e 100644 --- a/test/unit/devicestorage-test.js +++ b/test/unit/devicestorage-test.js @@ -10,7 +10,7 @@ var devicestorage_test = { asyncTest("Init", 3, function() { // init dependencies - devicestorage_test.util = new app.crypto.Util(window, uuid); + devicestorage_test.util = new cryptoLib.Util(window, uuid); devicestorage_test.jsonDao = new app.dao.LawnchairDAO(window); devicestorage_test.crypto = new app.crypto.Crypto(window, devicestorage_test.util); devicestorage_test.storage = new app.dao.DeviceStorage(devicestorage_test.util, devicestorage_test.crypto, devicestorage_test.jsonDao, null); diff --git a/test/unit/email-dao-test.js b/test/unit/email-dao-test.js index dfdb06d..f190d81 100644 --- a/test/unit/email-dao-test.js +++ b/test/unit/email-dao-test.js @@ -10,7 +10,7 @@ var emaildao_test = { asyncTest("Init", 3, function() { // init dependencies - var util = new app.crypto.Util(window, uuid); + var util = new cryptoLib.Util(window, uuid); var jsonDao = new app.dao.LawnchairDAO(window); emaildao_test.crypto = new app.crypto.Crypto(window, util); emaildao_test.storage = new app.dao.DeviceStorage(util, emaildao_test.crypto, jsonDao, null); diff --git a/test/unit/forge-test.js b/test/unit/forge-test.js index 65306ec..3cdc701 100644 --- a/test/unit/forge-test.js +++ b/test/unit/forge-test.js @@ -25,7 +25,7 @@ test("SHA-256 Hash", 1, function() { }); test("HMAC SHA-256", 1, function() { - var util = new app.crypto.Util(window, uuid); + var util = new cryptoLib.Util(window, uuid); var key = util.base642Str(util.random(forge_aes_test.keySize)); var iv = util.base642Str(util.random(forge_aes_test.keySize)); diff --git a/test/unit/rsa-test.js b/test/unit/rsa-test.js index dc927fe..95a7ae7 100644 --- a/test/unit/rsa-test.js +++ b/test/unit/rsa-test.js @@ -2,7 +2,7 @@ module("RSA Crypto"); var rsa_test = { keySize: 1024, - rsa: new app.crypto.RSA(forge, new app.crypto.Util(window, uuid)), + rsa: new cryptoLib.RSA(forge, new cryptoLib.Util(window, uuid)), test_message: '06a9214036b8a15b512e03d534120006' }; diff --git a/test/unit/util-test.js b/test/unit/util-test.js index 06e63d7..2c3b77b 100644 --- a/test/unit/util-test.js +++ b/test/unit/util-test.js @@ -11,14 +11,14 @@ test("JQuery and basic requirements", 7, function() { }); test("UUID", 2, function() { - var util = new app.crypto.Util(window, uuid); + var util = new cryptoLib.Util(window, uuid); var id = util.UUID(); ok(id, "UUID: " + id); ok(id.length === 36, "UUID length"); }); test("random", 3, function() { - var util = new app.crypto.Util(window, uuid); + var util = new cryptoLib.Util(window, uuid); var base64 = util.random(128); var str = window.atob(base64); ok(base64, "Random base64: " + base64); @@ -27,7 +27,7 @@ test("random", 3, function() { }); test("Parse Date", 1, function() { - var util = new app.crypto.Util(window, uuid); + var util = new cryptoLib.Util(window, uuid); var str = '1900-01-31 18:17:53'; var date = util.parseDate(str); var formated = util.formatDate(date); @@ -35,7 +35,7 @@ test("Parse Date", 1, function() { }); test("String -> Uint8Array -> String", 3, function() { - var util = new app.crypto.Util(window); + var util = new cryptoLib.Util(window); var input = "asdf"; var buf = util.binStr2Uint8Arr(input);