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:
parent
55abbc00cd
commit
9951a259a4
10
.gitignore
vendored
10
.gitignore
vendored
@ -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
|
@ -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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
@ -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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
Loading…
Reference in New Issue
Block a user