mirror of
https://github.com/moparisthebest/mail
synced 2024-11-25 10:22:18 -05:00
added rsa module and tests
This commit is contained in:
parent
ec14639d56
commit
6bbcd8cab7
@ -30,7 +30,6 @@ app.crypto.AesCBC = function(forge) {
|
|||||||
* @param ciphertext [String] The base64 encoded ciphertext
|
* @param ciphertext [String] The base64 encoded ciphertext
|
||||||
* @param key [String] The base64 encoded key
|
* @param key [String] The base64 encoded key
|
||||||
* @param iv [String] The base64 encoded IV
|
* @param iv [String] The base64 encoded IV
|
||||||
* @param iv [String] The base64 encoded HMAC
|
|
||||||
* @return [String] The decrypted plaintext in UTF8
|
* @return [String] The decrypted plaintext in UTF8
|
||||||
*/
|
*/
|
||||||
this.decrypt = function(ciphertext, key, iv) {
|
this.decrypt = function(ciphertext, key, iv) {
|
||||||
|
94
src/js/crypto/rsa.js
Normal file
94
src/js/crypto/rsa.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* A Wrapper for Forge's RSA encryption
|
||||||
|
*/
|
||||||
|
app.crypto.RSA = function(forge) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var publicKey = null,
|
||||||
|
privateKey = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
publicKey = forge.pki.publicKeyFromPem(pubkeyPem);
|
||||||
|
if (privkeyPem) {
|
||||||
|
privateKey = forge.pki.privateKeyFromPem(privkeyPem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate RSA keypair with the corresponding keysize
|
||||||
|
*/
|
||||||
|
this.generateKeypair = function(keySize, callback) {
|
||||||
|
forge.rsa.generateKeyPair({
|
||||||
|
bits: keySize,
|
||||||
|
workerScript: app.config.workerPath + '/../../lib/forge/prime.worker.js'
|
||||||
|
}, function(err, keypair) {
|
||||||
|
if (err || !keypair.publicKey || !keypair.privateKey) {
|
||||||
|
callback({
|
||||||
|
errMsg: 'RSA keygeneration failed!',
|
||||||
|
err: err
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKey = keypair.publicKey;
|
||||||
|
privateKey = keypair.privateKey;
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports user's keypair as PEMs
|
||||||
|
*/
|
||||||
|
this.exportKeys = function() {
|
||||||
|
return {
|
||||||
|
pubkeyPem: forge.pki.publicKeyToPem(publicKey),
|
||||||
|
privkeyPem: forge.pki.privateKeyToPem(privateKey)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt a String using RSA with PKCS#1 v1.5 padding
|
||||||
|
* @param plaintext [String] The input string in UTF8
|
||||||
|
* @return [String] The base64 encoded ciphertext
|
||||||
|
*/
|
||||||
|
this.encrypt = function(plaintext) {
|
||||||
|
var ct = publicKey.encrypt(plaintext);
|
||||||
|
return forge.util.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 UTF8
|
||||||
|
*/
|
||||||
|
this.decrypt = function(ciphertext) {
|
||||||
|
// parse base64 input to utf8
|
||||||
|
var ctUtf8 = forge.util.decode64(ciphertext);
|
||||||
|
return privateKey.decrypt(ctUtf8);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sign = function(input) {
|
||||||
|
var sha = forge.md.sha256.create();
|
||||||
|
sha.update(input);
|
||||||
|
|
||||||
|
var sig = privateKey.sign(sha);
|
||||||
|
return forge.util.encode64(sig);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.verify = function(input, sig) {
|
||||||
|
// parse base64 signature to utf8
|
||||||
|
var sigUtf8 = forge.util.decode64(sig);
|
||||||
|
|
||||||
|
var sha = forge.md.sha256.create();
|
||||||
|
sha.update(input);
|
||||||
|
|
||||||
|
return publicKey.verify(sha.digest().getBytes(), sigUtf8);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
@ -1,17 +1,11 @@
|
|||||||
module("AES Crypto");
|
module("AES Crypto");
|
||||||
|
|
||||||
var aes_test = {
|
var aes_test = {
|
||||||
keySize: 128
|
keySize: 128,
|
||||||
|
util: new app.crypto.Util(window, uuid),
|
||||||
|
test_message: new TestData().generateBigString(1000)
|
||||||
};
|
};
|
||||||
|
|
||||||
test("Init", 1, function() {
|
|
||||||
// init dependencies
|
|
||||||
aes_test.util = new app.crypto.Util(window, uuid);
|
|
||||||
ok(aes_test.util, 'Util');
|
|
||||||
// generate test data
|
|
||||||
aes_test.test_message = new TestData().generateBigString(1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("CBC mode", 4, function() {
|
test("CBC mode", 4, function() {
|
||||||
var aes = new app.crypto.AesCBC(forge);
|
var aes = new app.crypto.AesCBC(forge);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
module("Forge Crypto");
|
module("Forge Crypto");
|
||||||
|
|
||||||
var rsa_test = {
|
var forge_rsa_test = {
|
||||||
keySize: 1024,
|
keySize: 1024,
|
||||||
test_message: '06a9214036b8a15b512e03d534120006'
|
test_message: '06a9214036b8a15b512e03d534120006'
|
||||||
};
|
};
|
||||||
@ -13,15 +13,15 @@ var forge_aes_test = {
|
|||||||
test("SHA-1 Hash", 1, function() {
|
test("SHA-1 Hash", 1, function() {
|
||||||
var sha1 = forge.md.sha1.create();
|
var sha1 = forge.md.sha1.create();
|
||||||
sha1.update(forge_aes_test.test_message);
|
sha1.update(forge_aes_test.test_message);
|
||||||
var digest = sha1.digest().getBytes();
|
var digest = sha1.digest().toHex();
|
||||||
ok(digest);
|
ok(digest, digest);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("SHA-256 Hash", 1, function() {
|
test("SHA-256 Hash", 1, function() {
|
||||||
rsa_test.md = forge.md.sha256.create();
|
forge_rsa_test.md = forge.md.sha256.create();
|
||||||
rsa_test.md.update(forge_aes_test.test_message);
|
forge_rsa_test.md.update(forge_aes_test.test_message);
|
||||||
var digest = rsa_test.md.digest().getBytes();
|
var digest = forge_rsa_test.md.digest().toHex();
|
||||||
ok(digest);
|
ok(digest, digest);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("HMAC SHA-256", 1, function() {
|
test("HMAC SHA-256", 1, function() {
|
||||||
@ -34,85 +34,7 @@ test("HMAC SHA-256", 1, function() {
|
|||||||
hmac.start('sha256', key);
|
hmac.start('sha256', key);
|
||||||
hmac.update(iv);
|
hmac.update(iv);
|
||||||
hmac.update(forge_aes_test.test_message);
|
hmac.update(forge_aes_test.test_message);
|
||||||
var result = hmac.digest().toHex();
|
var digest = hmac.digest().toHex();
|
||||||
|
|
||||||
ok(result);
|
ok(digest, digest);
|
||||||
});
|
|
||||||
|
|
||||||
test("PBKDF2", 1, function() {
|
|
||||||
var util = new app.crypto.Util(window, uuid);
|
|
||||||
|
|
||||||
var salt = util.base642Str("vbhmLjC+Ub6MSbhS6/CkOwxB25wvwRkSLP2DzDtYb+4=");
|
|
||||||
var expect = '5223bd44b0523090b21e9d38a749b090';
|
|
||||||
|
|
||||||
var dk = forge.pkcs5.pbkdf2('password', salt, 1000, 16);
|
|
||||||
|
|
||||||
equal(expect, forge.util.bytesToHex(dk));
|
|
||||||
});
|
|
||||||
|
|
||||||
asyncTest("RSA Generate Keypair", 1, function() {
|
|
||||||
|
|
||||||
forge.rsa.generateKeyPair({
|
|
||||||
bits: rsa_test.keySize,
|
|
||||||
workerScript: app.config.workerPath + '/../lib/forge/prime.worker.js'
|
|
||||||
}, function(err, keypair) {
|
|
||||||
ok(!err && keypair);
|
|
||||||
|
|
||||||
rsa_test.keypair = keypair;
|
|
||||||
|
|
||||||
start();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test("RSA Encrypt", 1, function() {
|
|
||||||
rsa_test.ct = rsa_test.keypair.publicKey.encrypt(rsa_test.test_message);
|
|
||||||
ok(rsa_test.ct);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("RSA Decrypt", 1, function() {
|
|
||||||
var pt = rsa_test.keypair.privateKey.decrypt(rsa_test.ct);
|
|
||||||
equal(rsa_test.test_message, pt);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("RSA Sign", 1, function() {
|
|
||||||
var sha = forge.md.sha256.create();
|
|
||||||
sha.update(forge_aes_test.test_message);
|
|
||||||
|
|
||||||
rsa_test.sig = rsa_test.keypair.privateKey.sign(sha);
|
|
||||||
ok(rsa_test.sig);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("RSA Verify", 1, function() {
|
|
||||||
var res = rsa_test.keypair.publicKey.verify(rsa_test.md.digest().getBytes(), rsa_test.sig);
|
|
||||||
ok(res);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("AES-128-CBC Encrypt", 1, function() {
|
|
||||||
var util = new app.crypto.Util(window, uuid);
|
|
||||||
|
|
||||||
forge_aes_test.key = util.base642Str(util.random(forge_aes_test.keySize));
|
|
||||||
forge_aes_test.iv = util.base642Str(util.random(forge_aes_test.keySize));
|
|
||||||
var input = forge_aes_test.test_message;
|
|
||||||
|
|
||||||
// encrypt
|
|
||||||
var enCipher = forge.aes.createEncryptionCipher(forge_aes_test.key);
|
|
||||||
enCipher.start(forge_aes_test.iv);
|
|
||||||
enCipher.update(forge.util.createBuffer(input));
|
|
||||||
enCipher.finish();
|
|
||||||
|
|
||||||
forge_aes_test.ct = enCipher.output.getBytes();
|
|
||||||
ok(forge_aes_test.ct);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("AES-128-CBC Decrypt", 1, function() {
|
|
||||||
var input = forge_aes_test.test_message;
|
|
||||||
|
|
||||||
// decrypt
|
|
||||||
var deCipher = forge.aes.createDecryptionCipher(forge_aes_test.key);
|
|
||||||
deCipher.start(forge_aes_test.iv);
|
|
||||||
deCipher.update(forge.util.createBuffer(forge_aes_test.ct));
|
|
||||||
deCipher.finish();
|
|
||||||
|
|
||||||
equal(input, deCipher.output, 'En/Decrypt length: ' + input.length);
|
|
||||||
});
|
});
|
@ -42,6 +42,7 @@
|
|||||||
<script src="../js/crypto/util.js"></script>
|
<script src="../js/crypto/util.js"></script>
|
||||||
<script src="../js/crypto/pbkdf2.js"></script>
|
<script src="../js/crypto/pbkdf2.js"></script>
|
||||||
<script src="../js/crypto/aes-cbc.js"></script>
|
<script src="../js/crypto/aes-cbc.js"></script>
|
||||||
|
<script src="../js/crypto/rsa.js"></script>
|
||||||
<script src="../js/crypto/nacl-crypto.js"></script>
|
<script src="../js/crypto/nacl-crypto.js"></script>
|
||||||
<script src="../js/crypto/crypto.js"></script>
|
<script src="../js/crypto/crypto.js"></script>
|
||||||
|
|
||||||
@ -56,6 +57,7 @@
|
|||||||
<script src="util-test.js"></script>
|
<script src="util-test.js"></script>
|
||||||
<script src="forge-test.js"></script>
|
<script src="forge-test.js"></script>
|
||||||
<script src="aes-test.js"></script>
|
<script src="aes-test.js"></script>
|
||||||
|
<script src="rsa-test.js"></script>
|
||||||
<script src="nacl-crypto-test.js"></script>
|
<script src="nacl-crypto-test.js"></script>
|
||||||
<script src="crypto-test.js"></script>
|
<script src="crypto-test.js"></script>
|
||||||
<script src="localstorage-dao-test.js"></script>
|
<script src="localstorage-dao-test.js"></script>
|
||||||
|
50
test/unit/rsa-test.js
Normal file
50
test/unit/rsa-test.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
module("RSA Crypto");
|
||||||
|
|
||||||
|
var rsa_test = {
|
||||||
|
keySize: 1024,
|
||||||
|
rsa: new app.crypto.RSA(forge),
|
||||||
|
test_message: '06a9214036b8a15b512e03d534120006'
|
||||||
|
};
|
||||||
|
|
||||||
|
asyncTest("Generate keypair", 1, function() {
|
||||||
|
rsa_test.rsa.generateKeypair(rsa_test.keySize, function(err) {
|
||||||
|
ok(!err);
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Export keys", 2, function() {
|
||||||
|
rsa_test.keypair = rsa_test.rsa.exportKeys();
|
||||||
|
|
||||||
|
ok(rsa_test.keypair.pubkeyPem.indexOf('-----BEGIN PUBLIC KEY-----') === 0, rsa_test.keypair.pubkeyPem);
|
||||||
|
ok(rsa_test.keypair.privkeyPem.indexOf('-----BEGIN RSA PRIVATE KEY-----') === 0, rsa_test.keypair.privkeyPem);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Init", 2, function() {
|
||||||
|
rsa_test.rsa.init(rsa_test.keypair.pubkeyPem, rsa_test.keypair.privkeyPem);
|
||||||
|
var exported = rsa_test.rsa.exportKeys();
|
||||||
|
|
||||||
|
ok(exported.pubkeyPem.indexOf('-----BEGIN PUBLIC KEY-----') === 0);
|
||||||
|
ok(exported.privkeyPem.indexOf('-----BEGIN RSA PRIVATE KEY-----') === 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Encrypt", 1, function() {
|
||||||
|
rsa_test.ct = rsa_test.rsa.encrypt(rsa_test.test_message);
|
||||||
|
ok(rsa_test.ct);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Decrypt", 1, function() {
|
||||||
|
var pt = rsa_test.rsa.decrypt(rsa_test.ct);
|
||||||
|
equal(pt, rsa_test.test_message);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Sign", 1, function() {
|
||||||
|
rsa_test.sig = rsa_test.rsa.sign(rsa_test.test_message);
|
||||||
|
ok(rsa_test.sig);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Verify", 1, function() {
|
||||||
|
var res = rsa_test.rsa.verify(rsa_test.test_message, rsa_test.sig);
|
||||||
|
ok(res);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user