Шифрование картинок с помощью CryptoJS?

Стоит задача написать программу на JS (клиент онли), которая шифрует содержимое произвольных файлов (их может быть очень много и большого размера) с помощью введенного юзером пароля по стандартному криптостойкому алгоритму. После исследования требований выбрал алгоритм RC4 и его реализацию из библиотеки CryptoJS.

Сейчас имею такой код: https://jsfiddle.net/alexander_js_developer/nuevwrp0/.

Вводите пароль, хеш пароля - это ключ при шифровке и расшифровке файла. Текстовые файлы обрабатывает отлично (.txt, .js). А вот, например, картинки ломает нещадно. Я так понимаю, мне нужно конвертировать изображения в поток битов и шифровать уже его? Или есть другое, более правильное/быстрое решение?

Спасибо!


Ответы (1 шт):

Автор решения: Daniil Loban

Для работы с base64 понадобятся 2 функции

const fileToBase64 = file => new Promise((resolve, reject) => {
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = () => resolve(reader.result);
  reader.onerror = error => reject(error);
});

const base64ToFile = (url, filename, mimeType) => {
  return (fetch(url)
    .then(function(res){return res.arrayBuffer();})
    .then(function(buf){return new File([buf], filename,{type:mimeType});})
  );
}

( ссылки на исходный код fileToBase64, base64ToFile )

Существующие функции нужно будет подправить следующим образом, внедрив в них шаг кодирования и декодирования base64:

encryptNode.addEventListener('click', () => {
  if (!passNode.value) return alert('Password input is empty! Aborting.');
  const pass = CryptoJS.SHA3(passNode.value);
  pickAFile(false).then(async(file) => {
    const data = await fileToBase64(file)
    const encrypted = CryptoJS.RC4.encrypt(data, pass).toString();
    download(encrypted, `encrypted-${file.name}`, file.type);
  });
});

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 = async(e) => {
      try {
        const decrypted = CryptoJS.RC4.decrypt(e.target.result, pass);
        const typedArray = convertWordArrayToUint8Array(decrypted);
        const data = await base64ToFile(new TextDecoder().decode(typedArray),
         `decrypted-${file.name}`, file.type)
        download(data, `decrypted-${file.name}`, file.type);
      } catch (error) {
        console.log('wrong password!', error);
      }
    };
    reader.readAsText(file);
  });
});
→ Ссылка