I have code to encrypt files using RC4 algorithm. I was strongly advised to use a more reliable algorithm: AES. From the CryptoJS documentation, I understood that it works the same way as RC4. That is, the first argument is the string to be encrypted, and the second argument is the password string.
But simply replacing the RC4 method with AES did not help and I do not know where to look for the necessary information.
Thank you!
Here is my working (for RC4) code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js" integrity="sha512-E8QSvWZ0eCLGk4km3hxSsNmGWbLtSCSUcewDQPQWZF6pEU8GlT8a5fF32wOl1i8ftdMhssTrF/OhyGWwonTcXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div>
<h1>encrypt/decrypt file</h1>
<ol>
<li>Set password</li>
<li>Pick a file</li>
<li>Download decrypted/encrypted file</li>
</ol>
<div>
<input type="text" id="pass" placeholder="pass">
<button id="encrypt">encrypt file</button>
<button id="decrypt">decrypt file</button>
<button id="test">test</button>
</div>
</div>
<script>
// support
const download = (data, filename, type) => {
const file = new Blob([data], {
type: type
});
const a = document.createElement('a');
const url = URL.createObjectURL(file);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
};
const pickAFile = (getText = true) => {
return new Promise((resolve, reject) => {
const input = document.createElement('input');
input.type = 'file';
input.onchange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
if (!getText) {
resolve(file);
} else {
reader.onload = (e) => resolve(e.target.result);
reader.onerror = (e) => reject(e);
reader.readAsText(file);
}
};
input.click();
});
};
const convertWordArrayToUint8Array = (wordArray) => {
const arrayOfWords = wordArray.hasOwnProperty('words') ? wordArray.words : [];
const length = wordArray.hasOwnProperty('sigBytes') ?
wordArray.sigBytes :
arrayOfWords.length * 4;
const uInt8Array = new Uint8Array(length);
let index = 0;
let word;
let i;
for (i = 0; i < length; i++) {
word = arrayOfWords[i];
uInt8Array[index++] = word >> 24;
uInt8Array[index++] = (word >> 16) & 0xff;
uInt8Array[index++] = (word >> 8) & 0xff;
uInt8Array[index++] = word & 0xff;
}
return uInt8Array;
};
// /support
function app() {
const passNode = document.querySelector('input#pass');
const encryptNode = document.querySelector('#encrypt');
const decryptNode = document.querySelector('#decrypt');
encryptNode.addEventListener('click', () => {
if (!passNode.value) return alert('Password input is empty! Aborting.');
const pass = CryptoJS.SHA3(passNode.value);
pickAFile(false).then((file) => {
const reader = new FileReader();
reader.onload = (e) => {
const wordArray = CryptoJS.lib.WordArray.create(e.target.result);
const encrypted = CryptoJS.RC4.encrypt(wordArray, pass).toString();
download(encrypted, `encrypted-${file.name}`, file.type);
};
reader.readAsArrayBuffer(file);
});
});
decryptNode.addEventListener('click', () => {
if (!passNode.value) return alert('Password input is empty! Aborting.');
const pass = CryptoJS.SHA3(passNode.value);
pickAFile(false).then((file) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const decrypted = CryptoJS.RC4.decrypt(e.target.result, pass);
const typedArray = convertWordArrayToUint8Array(decrypted);
download(typedArray, `decrypted-${file.name}`, file.type);
} catch (error) {
console.log('wrong password!');
}
};
reader.readAsText(file);
});
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', app);
} else {
app();
}
</script>