reduce code duplication

This commit is contained in:
El RIDO 2018-10-20 22:34:36 +02:00
parent 717e5b0e57
commit 4c3fb3fe63
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92
3 changed files with 61 additions and 80 deletions

View File

@ -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 * @async
* @function * @function
* @private
* @param {string} mode of AES (ctr, cbc, cmac, gcm, cfb, kw)
* @param {string} key * @param {string} key
* @param {string} password * @param {string} password
* @param {string} message * @param {string} salt used in HMAC
* @return {string} data - JSON with encrypted data * @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 let keyArray = StrToArr(key);
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();
if ((password || '').trim().length > 0) { if ((password || '').trim().length > 0) {
keyArray += await window.crypto.subtle.digest( keyArray += await window.crypto.subtle.digest(
{name: 'SHA-256'}, {name: 'SHA-256'},
@ -739,33 +727,61 @@ jQuery.PrivateBin = (function($, RawDeflate) {
); );
// derive a stronger key for use with AES // 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 name: 'PBKDF2', // we use PBKDF2 for key derivation
salt: StrToArr(atob(object.salt)), // salt used in HMAC salt: StrToArr(atob(salt)), // salt used in HMAC
iterations: object.iter, // amount of iterations to apply iterations: iterations, // amount of iterations to apply
hash: {name: 'SHA-256'} // can be "SHA-1", "SHA-256", "SHA-384" or "SHA-512" hash: {name: 'SHA-256'} // can be "SHA-1", "SHA-256", "SHA-384" or "SHA-512"
}, },
importedKey, importedKey,
{ {
// can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC") // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
name: algo, name: 'AES-' + mode.toUpperCase(),
length: object.ks // can be 128, 192 or 256 length: keysize // can be 128, 192 or 256
}, },
false, // the key may not be exported false, // the key may not be exported
['encrypt'] // we may only use it for decryption ['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 // finally, encrypt message
const encrypted = await window.crypto.subtle.encrypt( 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") // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
name: algo, 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) 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) 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 StrToArr(compress(message)) // compressed plain text to encrypt
); );
object.ct = btoa(ArrToStr(encrypted)); object.ct = btoa(ArrToStr(encrypted));
@ -786,56 +802,21 @@ jQuery.PrivateBin = (function($, RawDeflate) {
me.decipher = async function(key, password, data) me.decipher = async function(key, password, data)
{ {
try { try {
let keyArray = StrToArr(key); const object = JSON.parse(data);
if ((password || '').trim().length > 0) { return decompress(
keyArray += await window.crypto.subtle.digest( ArrToStr(
{name: 'SHA-256'}, await window.crypto.subtle.decrypt(
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 name: algo, // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
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
);
// 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 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) 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) 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(atob(object.ct)) // cipher text to decrypt StrToArr(atob(object.ct)) // cipher text to decrypt
)
)
); );
return decompress(ArrToStr(decrypted));
} catch(err) { } catch(err) {
return ''; return '';
} }

View File

@ -70,7 +70,7 @@ if ($MARKDOWN):
endif; endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.7.js" integrity="sha512-VnKJHLosO8z2ojNvWk9BEKYqnhZyWK9rM90FgZUUEp/PRnUqR5OLLKE0a3BkVmn7YgB7LXRrjHgFHQYKd6DAIA==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-1.0.7.js" integrity="sha512-VnKJHLosO8z2ojNvWk9BEKYqnhZyWK9rM90FgZUUEp/PRnUqR5OLLKE0a3BkVmn7YgB7LXRrjHgFHQYKd6DAIA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-kn3yqj5KEEjhNS3Z/2WZT/e9vLtpxOXmeBbn1liPgw8EUvlSbDLdrSbcGKrDX16Zochji2pDMNMZOTLuTm9CFA==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-JNheFJ1QBN8s4U4lfDXguGVvnqJtrnt508Ew5PgAKWOTA2osRDgDJJYViz/A7XEd1NVAafN/qMDnIz/oqJkH/g==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->

View File

@ -48,7 +48,7 @@ if ($MARKDOWN):
endif; endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.7.js" integrity="sha512-VnKJHLosO8z2ojNvWk9BEKYqnhZyWK9rM90FgZUUEp/PRnUqR5OLLKE0a3BkVmn7YgB7LXRrjHgFHQYKd6DAIA==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-1.0.7.js" integrity="sha512-VnKJHLosO8z2ojNvWk9BEKYqnhZyWK9rM90FgZUUEp/PRnUqR5OLLKE0a3BkVmn7YgB7LXRrjHgFHQYKd6DAIA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-kn3yqj5KEEjhNS3Z/2WZT/e9vLtpxOXmeBbn1liPgw8EUvlSbDLdrSbcGKrDX16Zochji2pDMNMZOTLuTm9CFA==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-JNheFJ1QBN8s4U4lfDXguGVvnqJtrnt508Ew5PgAKWOTA2osRDgDJJYViz/A7XEd1NVAafN/qMDnIz/oqJkH/g==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->