reduce code duplication
This commit is contained in:
parent
717e5b0e57
commit
4c3fb3fe63
137
js/privatebin.js
137
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
|
* @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)
|
{
|
||||||
);
|
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)
|
||||||
// import raw key
|
tagLength: object.ts // the length of the tag you used to encrypt (if any)
|
||||||
const object = JSON.parse(data),
|
},
|
||||||
algo = 'AES-' + object.mode.toUpperCase(),
|
await deriveKey(object.mode, key, password, object.salt, object.iter, object.ks),
|
||||||
importedKey = await window.crypto.subtle.importKey(
|
StrToArr(atob(object.ct)) // cipher text to decrypt
|
||||||
'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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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) {
|
} catch(err) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -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]-->
|
||||||
|
@ -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]-->
|
||||||
|
Loading…
Reference in New Issue
Block a user