javascript - what - ¿Cómo puedo encriptar y desencriptar un blob pdf con forge y store en localStorage?
jwt with angularjs (1)
Su función decryptPDF
devuelve una cadena codificada en binario, que es el formato nativo forge v0.6.x que funciona. Para convertir eso de nuevo en un Uint8Array, haga esto en su lugar:
decipher.finish();
return s2a(decipher.output.getBytes());
function s2a(str) {
var view = new Uint8Array(str.length);
for (var i = 0, j = str.length; i < j; i++) {
view[i] = str.charCodeAt(i);
}
return view;
}
También debe verificar el valor de retorno de decipher.finish()
para asegurarse de que sea true
. De lo contrario, el descifrado puede haber fallado.
Intenté encriptar un Blob de archivo pdf y almacenarlo en el LocalStorage y leerlo y descifrarlo más tarde cuando estoy fuera de línea.
Mi aplicación está escrita en AngularJS y la encriptación se hace con forja
Aquí está mi código para descargar el archivo pdf:
$http.get(url, {
headers: {
"Application-Authorization": appContext.user.token
},
responseType: "blob"
}).then(function(response) {
backendCipherService.encryptPDF(response.data, appContext.user.password).then(function(data) {
$localForage.setItem("document::" + document.documentId + "::pdf", data.json).then(function(success) {
console.log("cached pdf", document.documentId);
deferred.resolve();
}, function(error) {
console.log("Error", response.data, document.documentName);
deferred.reject(error);
});
});
}, function(error) {
deferred.reject(error);
});
y aquí está mi código para cifrado y descifrado (backendCipherService):
this.encryptPDF = function(blob, password) {
var salt = forge.random.getBytesSync(256);
var key = forge.pkcs5.pbkdf2(password, salt, 40, 32);
var iv = forge.random.getBytesSync(32);
var cipher = forge.cipher.createCipher(''AES-CBC'', key);
cipher.start({iv: iv});
var deferred = $q.defer();
var uint8Array = null;
var arrayBuffer = null;
var fileReader = new FileReader();
fileReader.onload = function(progressEvent) {
arrayBuffer = this.result;
uint8Array = new Uint8Array(arrayBuffer);
};
fileReader.readAsArrayBuffer(blob);
fileReader.onloadend = function() {
var inp = uint8Array;
console.log(inp);
cipher.update(forge.util.createBuffer(inp));
cipher.finish();
var encrypted = cipher.output;
var data = forge.util.bytesToHex(encrypted);
var obj = {"salt": forge.util.bytesToHex(salt), "iv": forge.util.bytesToHex(iv), "encrypted": data};
deferred.resolve({
json: angular.toJson(obj)
});
};
return deferred.promise;
};
this.decryptPDF = function(json, password) {
var obj = angular.fromJson(json);
var key = forge.pkcs5.pbkdf2(password, forge.util.hexToBytes(obj.salt), 40, 32);
var iv = forge.util.createBuffer();
var data = forge.util.createBuffer();
iv.putBytes(forge.util.hexToBytes(obj.iv));
data.putBytes(forge.util.hexToBytes(obj.encrypted));
var decipher = forge.cipher.createDecipher(''AES-CBC'', key);
decipher.start({iv: iv});
decipher.update(data);
decipher.finish();
return decipher.output.data;
};
y aquí está el código para convertir el valor descifrado en una Blob nuevamente:
return $localForage.getItem("document::" + documentId + "::pdf").then(function(pdf) {
var pdfBlob = new Blob([backendCipherService.decryptPDF(pdf, appContext.user.password)], {type: ''application/pdf''});
return pdfBlob;
}, function(error) {
return error;
});
Esto en general funciona, pero el pdf no se puede leer desde PDF.js y me sale el error:
Error: Bad FCHECK in flate stream: 120, 194
pdf.worker.js:252 at error (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:252:15)
at Object.FlateStream (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:31394:7)
at Object.Parser_makeFilter [as makeFilter] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:30281:18)
at Object.Parser_filter [as filter] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:30259:25)
at Object.Parser_makeStream [as makeStream] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:30234:21)
at Object.Parser_getObj [as getObj] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:30022:28)
at Object.XRef_fetchUncompressed [as fetchUncompressed] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:4323:28)
at Object.XRef_fetch [as fetch] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:4280:26)
at Object.XRef_fetchIfRef [as fetchIfRef] (http://localhost:8080/client/components/pdfjs-dist/build/pdf.worker.js:4261:19)
pdf.worker.js:235 Warning: Unsupported feature "unknown"
pdf.worker.js:235 Warning: Invalid stream: "Error: Bad FCHECK in flate stream: 120, 194"
pdf.js:235 Warning: Unsupported feature "unknown"
Parece que el pdf está dañado de alguna manera.
Alguna idea de lo que está mal? Gracias