【问题标题】:How can i encrypt and decrypt a pdf blob with forge and store in localStorage?如何使用 forge 加密和解密 pdf blob 并存储在 localStorage 中?
【发布时间】:2015-04-19 13:21:48
【问题描述】:

我正在尝试加密一个 pdf 文件的 Blob 并将其存储在 localStorage 中,然后在我离线时读取和解密它。

我的应用是用 AngularJS 编写的,加密是用 forge 完成的

这是我下载 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);
                });

这是我的加密和解密代码(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;
        };

这是将解密后的值再次转换为 Blob 的代码:

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

这通常有效,但无法从 PDF.js 读取 pdf,我收到错误:

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"

似乎 pdf 以某种方式损坏。

任何想法有什么问题吗? 谢谢

【问题讨论】:

    标签: javascript angularjs encryption local-storage forge


    【解决方案1】:

    您的decryptPDF 函数返回一个二进制编码的字符串,这是forge v0.6.x 使用的本机格式。要将其转换回 Uint8Array,请改为:

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

    您还应该检查decipher.finish() 的返回值以确保它是true。否则可能解密失败。

    【讨论】:

      猜你喜欢
      • 2014-11-07
      • 2018-03-05
      • 1970-01-01
      • 2019-06-21
      • 2020-01-10
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多