我试图加密一个 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 似乎已损坏。
任何想法有什么问题吗?
谢谢
Your 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
。否则,解密可能会失败。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)