2016-11-28 2 views
3

Я пытаюсь написать приложение для сквозного шифрования файлов с JS в браузере. Однако, похоже, я не могу правильно дешифровать все файлы.CryptoJS - расшифровать зашифрованный файл

TL; DR Как нецелесообразно шифровать файлы размером более 1 МБ в целом, я пытаюсь зашифровать их куском. После этого я пытаюсь написать зашифрованные слова (полученные из WordArray 2) в blob. Что касается дешифрования, я прочитал файлы и разделил их на куски в соответствии с созданной картой при шифровании кусков и попытался их расшифровать. Проблема заключается в расшифровке результата - 0 бит!

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

Больше объяснения

Я использую CryptoJS AES с настройками по умолчанию.

Прямо сейчас мой код выглядит следующим образом:

function encryptFile (file, options, resolve, reject) { 
    if (!options.encrypt) { 
    return resolve(file) 
    } 
    if (!options.processor || !options.context) { 
    return reject('No encryption method.') 
    } 

    function encryptBlob (file, optStart, optEnd) { 
    const start = optStart || 0 
    let stop = optEnd || CHUNK_SIZE 
    if (stop > file.size - 1) { 
     stop = file.size 
    } 

    const blob = file.slice(start, stop) 
    const fileReader = new FileReader() 

    fileReader.onloadend = function() { 
     if (this.readyState !== FileReader.DONE) return 

     const index = Math.ceil(optStart/CHUNK_SIZE) 
     const result = CryptoJS.lib.WordArray.create(this.result) 
     encryptedFile[index] = encrypt(result) 

     chunksResolved++ 
     if (chunksResolved === count) { 
     const {sigBytes, sigBytesMap, words} = getCipherInfo(encryptedFile) 
     const blob = getBlob(sigBytes, words) 

     resolve(blob, Object.keys(sigBytesMap)) 
     } 
    } 
    fileReader.readAsArrayBuffer(blob) 
    } 

    let chunksResolved = 0 
    const encryptedFile = [] 
    const CHUNK_SIZE = 1024*1024 
    const count = Math.ceil(file.size/CHUNK_SIZE) 
    const encrypt = value => options.processor.call(
    options.context, value, 'file', 
    (v, k) => CryptoJS.AES.encrypt(v, k)) 

    for (let start = 0; (start + CHUNK_SIZE)/CHUNK_SIZE <= count; start+= CHUNK_SIZE) { 
    encryptBlob(file, start, start + CHUNK_SIZE - 1) 
    } 
} 

Как вы можете видеть, что я пытаюсь прочитать файл кусок от куска (каждый фрагмент 1 МБ или fileSize % 1MB), как ArrayBuffer, преобразовав его в WordArray для CryptoJS, чтобы понять и зашифровать его.

После шифрования всех ломти я стараюсь писать каждое слово, которое они имеют в сгустка (используя код, который я нашел в вопросах CryptoJS в Google Code, упомянутый ниже) и я думаю вот что идет не так. Я также создал карту, где заканчиваются зашифрованные фрагменты, поэтому я могу позже использовать ее для получения фрагментов из двоичного файла для дешифрования.

И вот как я расшифровать файлы:

function decryptFile (file, sigBytesMap, filename, options, resolve, reject) { 
    if (!options.decrypt) { 
    return resolve(file) 
    } 
    if (!options.processor || !options.context) { 
    return reject('No decryption method.') 
    } 

    function decryptBlob (file, index, start, stop) { 
    const blob = file.slice(start, stop) 
    const fileReader = new FileReader() 

    fileReader.onloadend = function() { 
     if (this.readyState !== FileReader.DONE) return 

     const result = CryptoJS.lib.WordArray.create(this.result) 
     decryptedFile[index] = decrypt(result) 

     chunksResolved++ 
     if (chunksResolved === count) { 
     const {sigBytes, words} = getCipherInfo(decryptedFile) 
     const finalFile = getBlob(sigBytes, words) 

     resolve(finalFile, filename) 
     } 
    } 
    fileReader.readAsArrayBuffer(blob) 
    } 

    let chunksResolved = 0 
    const count = sigBytesMap.length 
    const decryptedFile = [] 
    const decrypt = value => options.processor.call(
    options.context, value, 'file', 
    (v, k) => CryptoJS.AES.decrypt(v, k)) 

    for (let i = 0; i < count; i++) { 
    decryptBlob(file, i, parseInt(sigBytesMap[i - 1]) || 0, parseInt(sigBytesMap[i]) - 1) 
    } 
} 

дешифрование это так же, как шифрование, но не работает. Хотя куски уже не 1 МБ, они ограничены sigBytes, упомянутыми на карте. Для расшифровки нет результата! sigBytes: 0.

Вот код для создания блобы и получений sigbytesMap:

function getCipherInfo (ciphers) { 
    const sigBytesMap = [] 
    const sigBytes = ciphers.reduce((tmp, cipher) => { 
    tmp += cipher.sigBytes || cipher.ciphertext.sigBytes 
    sigBytesMap.push(tmp) 
    return tmp 
    }, 0) 

    const words = ciphers.reduce((tmp, cipher) => { 
    return tmp.concat(cipher.words || cipher.ciphertext.words) 
    }, []) 

    return {sigBytes, sigBytesMap, words} 
} 

function getBlob (sigBytes, words) { 
    const bytes = new Uint8Array(sigBytes) 
    for (var i = 0; i < sigBytes; i++) { 
    const byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff 
    bytes[i] = byte 
    } 

    return new Blob([ new Uint8Array(bytes) ]) 
} 

Я предполагаю, что этот вопрос является методом я использую для чтения зашифрованных ломтей. Или, может быть, написать их!

Следует также упомянуть, что ранее я делал что-то другое для шифрования. Я строчил каждый WordArray, полученный в качестве результата для CryptoJS.AES.encrypt, используя метод toString с кодировкой по умолчанию (который, я считаю, CryptoJS.enc.Hex), но некоторые файлы не были дешифрованы правильно. Это не имело никакого отношения к размеру исходного файла, а не к его типам. Опять же, я угадываю!

+1

1) Почему вы это делаете? 2) Знаете ли вы, что это небезопасно? Что именно вы достигаете с помощью этого шифрования? Так как это браузер для браузера - ключ будет виден, так в чем смысл? – Mjh

+1

Является ли 'k' жестко закодированным или извлекается через асимметричный крипто? –

+0

@Mjh Чтобы достичь нулевого знания, мы не будем иметь доступ к данным пользователя. – MahdiPOnline

ответ

0

Оказалось, что проблема была WordArray, на которую ссылается CryptoJS.AES.decrypt(value, key), имеет 4 дополнительных слова в качестве отступов, которые не должны включаться в окончательный результат. CryptoJS пытается разобрать результат, но только изменения sigBytes соответственно и не изменяет words. Поэтому при расшифровке, прежде чем писать фрагменты в файл, поп эти лишние слова. 4 слова для полных кусков и 3 для меньших (последний кусок).

Смежные вопросы