diff --git a/js/privatebin.js b/js/privatebin.js
index c22c8c2..c3ece7b 100644
--- a/js/privatebin.js
+++ b/js/privatebin.js
@@ -693,35 +693,23 @@ jQuery.PrivateBin = (function($, RawDeflate) {
}
/**
- * compress, then encrypt message with given key and password
+ * derive cryptographic key from key string and password
*
- * @name CryptTool.cipher
+ * @name CryptTool.deriveKey
* @async
* @function
+ * @private
+ * @param {string} mode of AES (ctr, cbc, cmac, gcm, cfb, kw)
* @param {string} key
* @param {string} password
- * @param {string} message
- * @return {string} data - JSON with encrypted data
+ * @param {string} salt used in HMAC
+ * @param {int} iterations amount to apply
+ * @param {int} keysize (128, 192 or 256)
+ * @return {CryptoKey} derived key
*/
- me.cipher = async function(key, password, message)
+ async function deriveKey(mode, key, password, salt, iterations, keysize)
{
- // AES in Galois Counter Mode, keysize 256 bit, authentication tag 128 bit, 10000 iterations in key derivation
- const iv = getRandomBytes(16),
- salt = getRandomBytes(8);
- let object = {
- iv: btoa(iv),
- v: 1,
- iter: 10000,
- ks: 256,
- ts: 128,
- mode: 'gcm',
- adata: '', // if used, base64 encode it with btoa()
- cipher: 'aes',
- salt: btoa(salt)
- },
- keyArray = StrToArr(key);
- const algo = 'AES-' + object.mode.toUpperCase();
-
+ let keyArray = StrToArr(key);
if ((password || '').trim().length > 0) {
keyArray += await window.crypto.subtle.digest(
{name: 'SHA-256'},
@@ -739,33 +727,61 @@ jQuery.PrivateBin = (function($, RawDeflate) {
);
// derive a stronger key for use with AES
- const derivedKey = await window.crypto.subtle.deriveKey(
+ return await window.crypto.subtle.deriveKey(
{
name: 'PBKDF2', // we use PBKDF2 for key derivation
- salt: StrToArr(atob(object.salt)), // salt used in HMAC
- iterations: object.iter, // amount of iterations to apply
+ salt: StrToArr(atob(salt)), // salt used in HMAC
+ iterations: iterations, // amount of iterations to apply
hash: {name: 'SHA-256'} // can be "SHA-1", "SHA-256", "SHA-384" or "SHA-512"
},
importedKey,
{
// can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
- name: algo,
- length: object.ks // can be 128, 192 or 256
+ name: 'AES-' + mode.toUpperCase(),
+ length: keysize // can be 128, 192 or 256
},
false, // the key may not be exported
['encrypt'] // we may only use it for decryption
);
+ }
+
+ /**
+ * compress, then encrypt message with given key and password
+ *
+ * @name CryptTool.cipher
+ * @async
+ * @function
+ * @param {string} key
+ * @param {string} password
+ * @param {string} message
+ * @return {string} data - JSON with encrypted data
+ */
+ me.cipher = async function(key, password, message)
+ {
+ // AES in Galois Counter Mode, keysize 256 bit, authentication tag 128 bit, 10000 iterations in key derivation
+ const iv = getRandomBytes(16);
+ let object = {
+ iv: btoa(iv),
+ v: 1,
+ iter: 10000,
+ ks: 256,
+ ts: 128,
+ mode: 'gcm',
+ adata: '', // if used, base64 encode it with btoa()
+ cipher: 'aes',
+ salt: btoa(getRandomBytes(8))
+ };
// finally, encrypt message
const encrypted = await window.crypto.subtle.encrypt(
{
// can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
name: algo,
- iv: StrToArr(atob(object.iv)), // the initialization vector you used to encrypt
+ iv: StrToArr(iv), // the initialization vector you used to encrypt
additionalData: StrToArr(atob(object.adata)), // the addtional data you used during encryption (if any)
tagLength: object.ts // the length of the tag you used to encrypt (if any)
},
- derivedKey,
+ await deriveKey(object.mode, key, password, object.salt, object.iter, object.ks),
StrToArr(compress(message)) // compressed plain text to encrypt
);
object.ct = btoa(ArrToStr(encrypted));
@@ -786,56 +802,21 @@ jQuery.PrivateBin = (function($, RawDeflate) {
me.decipher = async function(key, password, data)
{
try {
- let keyArray = StrToArr(key);
- if ((password || '').trim().length > 0) {
- keyArray += await window.crypto.subtle.digest(
- {name: 'SHA-256'},
- StrToArr(password)
- );
- }
-
- // import raw key
- const object = JSON.parse(data),
- algo = 'AES-' + object.mode.toUpperCase(),
- importedKey = await window.crypto.subtle.importKey(
- 'raw', // only 'raw' is allowed
- keyArray,
- {name: 'PBKDF2'}, // we use PBKDF2 for key derivation
- false, // the key may not be exported
- ['deriveKey'] // we may only use it for key derivation
- );
-
- // derive a stronger key for use with AES
- const derivedKey = await window.crypto.subtle.deriveKey(
- {
- name: 'PBKDF2', // we use PBKDF2 for key derivation
- salt: StrToArr(atob(object.salt)), // salt used in HMAC
- iterations: object.iter, // amount of iterations to apply
- hash: {name: 'SHA-256'} // can be "SHA-1", "SHA-256", "SHA-384" or "SHA-512"
- },
- importedKey,
- {
- // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
- name: algo,
- length: object.ks // can be 128, 192 or 256
- },
- false, // the key may not be exported
- ['decrypt'] // we may only use it for decryption
+ const object = JSON.parse(data);
+ return decompress(
+ ArrToStr(
+ await window.crypto.subtle.decrypt(
+ {
+ name: algo, // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
+ iv: StrToArr(atob(object.iv)), // the initialization vector you used to encrypt
+ additionalData: StrToArr(atob(object.adata)), // the addtional data you used during encryption (if any)
+ tagLength: object.ts // the length of the tag you used to encrypt (if any)
+ },
+ await deriveKey(object.mode, key, password, object.salt, object.iter, object.ks),
+ StrToArr(atob(object.ct)) // cipher text to decrypt
+ )
+ )
);
-
- // finally, decrypt message
- const decrypted = await window.crypto.subtle.decrypt(
- {
- // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
- name: algo,
- iv: StrToArr(atob(object.iv)), // the initialization vector you used to encrypt
- additionalData: StrToArr(atob(object.adata)), // the addtional data you used during encryption (if any)
- tagLength: object.ts // the length of the tag you used to encrypt (if any)
- },
- derivedKey,
- StrToArr(atob(object.ct)) // cipher text to decrypt
- );
- return decompress(ArrToStr(decrypted));
} catch(err) {
return '';
}
diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php
index 21b0a8e..03dd724 100644
--- a/tpl/bootstrap.php
+++ b/tpl/bootstrap.php
@@ -70,7 +70,7 @@ if ($MARKDOWN):
endif;
?>
-
+
diff --git a/tpl/page.php b/tpl/page.php
index e78856a..b6a245d 100644
--- a/tpl/page.php
+++ b/tpl/page.php
@@ -48,7 +48,7 @@ if ($MARKDOWN):
endif;
?>
-
+