Comment puis-je chiffrer et décrypter un blob pdf avec forge et store dans localStorage?

J'ai essayé de chiffrer un fichier Blob de pdf et de le stocker dans le stockage local et de le lire et le décrypter plus tard lorsque je ne suis pas connecté.

Mon application est écrite dans AngularJS et le cryptage se fait avec forge

Voici mon code pour télécharger le fichier 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); }); 

Et voici mon code pour le cryptage et le décryptage (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; }; 

Et voici le code pour convertir la valeur déchiffrée en Blob à nouveau:

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

Ceci en général fonctionne mais le pdf ne peut pas être lu à partir de PDF.js et je reçois l'erreur:

 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" 

Il semble que le pdf soit corrompu de quelque façon.

Une idée de ce qui ne va pas? THX

Votre fonction decryptPDF renvoie une chaîne codée en binaire, dont le format natif forge v0.6.x fonctionne. Pour convertir cela de nouveau en Uint8Array, faites ceci à la place:

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

Vous devriez également vérifier la valeur de retour de decipher.finish() pour s'assurer qu'il est true . Sinon, le décryptage peut avoir échoué.