1
0
mirror of https://github.com/moparisthebest/mail synced 2024-12-21 23:08:50 -05:00

swapped crypto'js cbc impl for forge

This commit is contained in:
Tankred Hase 2013-05-14 12:49:27 +02:00
parent 2b50bc2308
commit 4d47a3cdec
2 changed files with 57 additions and 45 deletions

View File

@ -1,55 +1,81 @@
/**
* A Wrapper for Crypto.js's AES-CBC encryption
* A Wrapper for Forge's AES-CBC encryption with HMAC-SHA-256 an integrify check
*/
app.crypto.AesCBC = function() {
'use strict';
var mode = CryptoJS.mode.CBC; // use CBC mode for Crypto.js
var padding = CryptoJS.pad.Pkcs7; // use Pkcs7/Pkcs5 padding for Crypto.js
/**
* Encrypt a String using AES-CBC-Pkcs7 using the provided keysize (e.g. 128, 256)
* and create an HMAC-SHA-265 for integrity check
* @param plaintext [String] The input string in UTF8
* @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) {
// parse base64 input to crypto.js WordArrays
var keyWords = CryptoJS.enc.Base64.parse(key);
var ivWords = CryptoJS.enc.Base64.parse(iv);
var plaintextWords = CryptoJS.enc.Utf8.parse(plaintext);
// parse base64 input to utf8
var keyUtf8 = forge.util.decode64(key);
var ivUtf8 = forge.util.decode64(iv);
var encrypted = CryptoJS.AES.encrypt(plaintextWords, keyWords, {
iv: ivWords,
mode: mode,
padding: padding
});
var ctBase64 = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
// encrypt
var cipher = forge.aes.createEncryptionCipher(keyUtf8);
cipher.start(ivUtf8);
cipher.update(forge.util.createBuffer(plaintext));
cipher.finish();
var ctUtf8 = cipher.output.getBytes();
return ctBase64;
// get hmac
return {
hmac: this.getHmac(ctUtf8, keyUtf8, ivUtf8),
ciphertext: forge.util.encode64(ctUtf8)
};
};
/**
* Decrypt a String using AES-CBC-Pkcs7 using the provided keysize (e.g. 128, 256)
* and does an HMAC-SHA-265 integrity check
* @param ciphertext [String] The base64 encoded ciphertext
* @param key [String] The base64 encoded key
* @param iv [String] The base64 encoded IV
* @param iv [String] The base64 encoded HMAC
* @return [String] The decrypted plaintext in UTF8
*/
this.decrypt = function(ciphertext, key, iv) {
// parse base64 input to crypto.js WordArrays
var keyWords = CryptoJS.enc.Base64.parse(key);
var ivWords = CryptoJS.enc.Base64.parse(iv);
this.decrypt = function(ciphertext, key, iv, hmac) {
// parse base64 input to utf8
var ctUtf8 = forge.util.decode64(ciphertext);
var keyUtf8 = forge.util.decode64(key);
var ivUtf8 = forge.util.decode64(iv);
var decrypted = CryptoJS.AES.decrypt(ciphertext, keyWords, {
iv: ivWords,
mode: mode,
padding: padding
});
var pt = decrypted.toString(CryptoJS.enc.Utf8);
// check hmac
var checkedHmac = this.getHmac(ctUtf8, keyUtf8, ivUtf8);
if (hmac !== checkedHmac) {
throw new Error('The integrity check via HMAC failed!');
}
return pt;
var cipher = forge.aes.createDecryptionCipher(keyUtf8);
cipher.start(ivUtf8);
cipher.update(forge.util.createBuffer(ctUtf8));
cipher.finish();
return cipher.output.getBytes();
};
/**
* Generate a base64 encoded HMAC using SHA-265
* @param input [String] The input string in UTF8
* @param key [String] The UTF8 encoded key
* @param iv [String] The UTF8 encoded IV
* @return [String] The base64 encoded hmac
*/
this.getHmac = function(input, key, iv) {
var hmac = forge.hmac.create();
hmac.start('sha256', key);
if (iv) {
hmac.update(iv);
}
hmac.update(input);
return forge.util.encode64(hmac.digest().getBytes());
};
};

View File

@ -12,7 +12,7 @@ test("Init", 1, function() {
aes_test.test_message = new TestData().generateBigString(1000);
});
test("CBC mode", 4, function() {
test("CBC mode with HMAC-SHA-256", 4, function() {
var aes = new app.crypto.AesCBC();
var plaintext = aes_test.test_message;
@ -21,10 +21,10 @@ test("CBC mode", 4, function() {
ok(key, 'Key: ' + key);
equal(CryptoJS.enc.Base64.parse(key).sigBytes * 8, aes_test.keySize, 'Keysize ' + aes_test.keySize);
var ciphertext = aes.encrypt(plaintext, key, iv);
ok(ciphertext, 'Ciphertext lenght: ' + ciphertext.length);
var ct = aes.encrypt(plaintext, key, iv);
ok(ct.ciphertext, 'Ciphertext lenght: ' + ct.ciphertext.length);
var decrypted = aes.decrypt(ciphertext, key, iv);
var decrypted = aes.decrypt(ct.ciphertext, key, iv, ct.hmac);
equal(decrypted, plaintext, 'Decryption correct' + decrypted);
});
@ -40,18 +40,4 @@ test("CCM mode", 2, function() {
var decrypted = aes.decrypt(ciphertext, key, iv);
equal(decrypted, plaintext, 'Decryption correct: ' + decrypted);
});
// test("GCM mode", 2, function() {
// var aes = new app.crypto.AesGCM();
//
// 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);
// });
});