2016-11-28 23 views
3

Ich versuche eine Anwendung zu schreiben Ende-zu-Ende-Verschlüsselung für Dateien mit JS im Browser zu schreiben. Jedoch scheint es mir nicht möglich zu sein, alle Dateien korrekt entschlüsseln zu lassen.CryptoJS - Eine verschlüsselte Datei entschlüsseln

TL; DR Da es unpraktisch ist, Dateien, die größer als 1 MB sind, als Ganzes zu verschlüsseln, versuche ich, sie Stück für Stück zu verschlüsseln. Danach versuche ich die verschlüsselten Wörter (resultierend aus Wordarray CryptoJS) in einen Blob zu schreiben. Wie bei der Entschlüsselung lese ich die Dateien und teile sie in Blöcke entsprechend der Karte, die beim Verschlüsseln der Blöcke erzeugt wurde, und versuche sie zu entschlüsseln. Das Problem ist entschlüsselt Ergebnis ist 0 Bits!

Ich denke, ich lese nicht die Stücke beim Entschlüsseln korrekt. Bitte beachten Sie den folgenden Code für die Funktion getBlob (Schreiben von Daten in den Blob) und den letzten Teil von decryptFile zum Lesen von Chunks.

Weitere Erklärung

Ich verwende CryptoJS AES mit den Standardeinstellungen.

Im Moment sieht mein Code wie folgt aus:

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) 
    } 
} 

Wie Sie sehen, ich versuche, die Datei Chunk Chunk zu lesen (jeder Chunk ist 1MB oder fileSize % 1MB) als Arraybuffer, um es zu WordArray Umwandlung für CryptoJS zu verstehen und zu verschlüsseln.

Nachdem alle Stücke Verschlüsselung Ich versuche jedes Wort, das sie zu einem Blob zu schreiben haben (einen Code ich in CryptoJS Fragen in Google Code gefunden, unten erwähnt) und ich hier denke, ist das, was schief geht. Ich habe auch eine Karte erstellt, wo verschlüsselte Chunks enden, damit ich sie später benutzen kann, um die Chunks aus der Binärdatei zur Entschlüsselung zu bekommen.

Und hier ist, wie ich entschlüsseln Sie die Dateien:

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) 
    } 
} 

Decryption genau wie die Verschlüsselung ist aber nicht funktioniert. Obwohl Chunks nicht mehr 1MB groß sind, sind sie auf sigBytes beschränkt, die in der Karte erwähnt werden. Es gibt kein Ergebnis für die Entschlüsselung! sigBytes: 0.

Hier ist der Code für einen Blob zu erzeugen und sigbytesMap bekommen:

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) ]) 
} 

Ich vermute, das Problem ist die Methode, die ich die verschlüsselten Stücke lesen bin mit. Oder vielleicht schreibe ich sie!

Ich sollte auch erwähnen, dass ich vorher etwas anderes für die Verschlüsselung gemacht habe. Ich zeichnete jedes WordArray, das ich als Ergebnis für CryptoJS.AES.encrypt mit der toString-Methode mit der Standardcodierung erhielt (was ich glaube, ist CryptoJS.enc.Hex) aber einige Dateien nicht korrekt entschlüsseln. Es hatte nichts mit der Größe der Originaldatei zu tun, sondern mit ihrer Art. Ich vermute wieder!

+1

1) Warum machst du das? 2) Weißt du, dass das unsicher ist? Was genau erreichen Sie mit dieser Verschlüsselung? Da es Browser zu Browser ist - Schlüssel wird sichtbar sein, also was ist der Sinn? – Mjh

+1

Ist 'k' hart codiert oder wird es durch asymmetrische Verschlüsselung abgerufen? –

+0

@Mjh Um Zero-Knowledge-Verschlüsselung zu erreichen, hätten wir keinen Zugriff auf Benutzerdaten. – MahdiPOnline

Antwort

0

Es stellte sich heraus, das Problem war die WordArray zurückgegeben von CryptoJS.AES.decrypt(value, key) hat 4 zusätzliche Wörter als Padding, die nicht im Endergebnis enthalten sein sollte. CryptoJS versucht, das Ergebnis nicht zu puffern, ändert aber nur sigBytes entsprechend und ändert nicht words. Also, beim Entschlüsseln, vor dem Schreiben von Stücken in die Datei pop diese zusätzlichen Wörter. 4 Wörter für volle Chunks und 3 für kleinere Chunks.

Verwandte Themen