title: How can i encrypt and decrypt a pdf blob with forge and store in localStorage?
body: <p>I've trying to encrypt a Blob of pdf file and store it in the localStorage and read and decrypt it later when i'm offline.</p>
  
  <p>My app is written in AngularJS and the encryption is done with <a href="https://github.com/digitalbazaar/forge" rel="nofollow">forge</a></p>
  
  <p>Here is my code for downloading the pdf file:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>$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);
                  });</code></pre>
  </div>
  </div>
  </p>
  
  <p>and here is my code for encryption and decryption (backendCipherService):</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>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;
          };</code></pre>
  </div>
  </div>
  </p>
  
  <p>and here is the code for converting the decrypted value to a Blob again:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>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;
              });</code></pre>
  </div>
  </div>
  </p>
  
  <p>This in general works but the pdf can not be read from PDF.js and i get the error:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>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"</code></pre>
  </div>
  </div>
  </p>
  
  <p>It seems that the pdf is corrupted somehow. </p>
  
  <p>Any ideas what's wrong?
  Thx</p>