我试图加密一个blof的pdf文件并将其存储在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无法从PDF.js中读取,我收到错误:
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以某种方式被破坏了。
任何想法有什么不对? THX
答案 0 :(得分:1)
您的decryptPDF
函数返回二进制编码的字符串,这是for v v.6.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
。否则,解密可能已失败。