我正在开发制作 PAdES 签名的 webapp。我已成功实施 PAdES Baseline-B。但是,当我尝试通过添加此处描述的所有必要信息(包括 OCSP 响应、CRL 和证书)来创建 PAdES Baseline-LT 时,文件似乎已损坏并且 Adobe 显示以下错误:签名验证期间出错:PKCS7解析错误
如果您想查看,这里是签名的 PDF:https ://easyupload.io/fxkzvs
我在签署 PDF 后附加 DSS,所以我附加以获取 LT 子类型的那些附加对象不会影响签名本身,所以我不确定为什么我会收到 PKCS7 错误,如果我制作的签名相同(创建时基线-B) 似乎很好。
这是创建和插入这些附加数据的代码部分:
public appendVri(pdfRaw, pdfToSign, vri: VRI) {
if (pdfRaw instanceof ArrayBuffer) {
pdfRaw = new Uint8Array(pdfRaw);
}
const pdf = this.loadPdf(pdfRaw);
const root = this.findRootEntry(pdf.xref);
const rootSuccessor = this.findSuccessorEntry(pdf.xref.entries, root);
const certsEntry = [];
const xObjects = [];
let offsetDss;
let offsetVri;
// let offsetCerts[];
// let offsetOcsp[];
// let offsetCrls[];
const dummy = this.findFreeXrefNr(pdf.xref.entries, xObjects);
xObjects.push(dummy);
const dssEntry = this.findFreeXrefNr(pdf.xref.entries, xObjects);
xObjects.push(dssEntry);
const vriEntry = this.findFreeXrefNr(pdf.xref.entries, xObjects);
xObjects.push(vriEntry);
for (let i = 0; i < vri.certs.length; i++) {
certsEntry[i] = this.findFreeXrefNr(pdf.xref.entries, xObjects);
xObjects.push(certsEntry[i]);
}
const ocspEntry = [];
for (let i = 0; i < vri.OCSPs.length; i++) {
ocspEntry[i] = this.findFreeXrefNr(pdf.xref.entries, xObjects);
xObjects.push(ocspEntry[i]);
}
const crlsEntry = [];
for (let i = 0; i < vri.CRLs.length; i++) {
crlsEntry[i] = this.findFreeXrefNr(pdf.xref.entries, xObjects);
xObjects.push(crlsEntry[i]);
}
let certsReference = '/Certs [';
for (let i = 0; i < vri.certs.length; i++) {
certsReference = certsReference + certsEntry[i] + ' 0 R';
if (i === vri.certs.length - 1) {
certsReference = certsReference + '] \n';
} else {
certsReference = certsReference + ' ';
}
}
let ocspReference = '/OCSPs [';
for (let i = 0; i < vri.OCSPs.length; i++) {
ocspReference = ocspReference + ocspEntry[i] + ' 0 R';
if (i === vri.OCSPs.length - 1) {
ocspReference = ocspReference + '] \n';
} else {
ocspReference = ocspReference + ' ';
}
}
let crlsReference = '/CRLs [';
for (let i = 0; i < vri.CRLs.length; i++) {
crlsReference = crlsReference + crlsEntry[i] + ' 0 R';
if (i === vri.CRLs.length - 1) {
crlsReference = crlsReference + '] \n';
} else {
crlsReference = crlsReference + ' ';
}
}
const offsets = [];
const appendDss = '\n' + pdfToSign.dssEntry + ' 0 obj\n' +
'<< \n' +
'/VRI ' + vriEntry + ' 0 R \n' +
certsReference +
ocspReference +
crlsReference +
'>>';
offsetDss = (pdf.stream.bytes.length);
offsets.push(offsetDss);
let array = this.insertIntoArray(pdf.stream.bytes, offsetDss, appendDss);
const sigHash = this.strHex(this.digest(forge.util.decode64(pdfToSign.sig), 'SHA1')).toUpperCase();
const appendVri = '\n' + vriEntry + ' 0 obj\n' +
'<< \n' +
'/' + sigHash + ' << \n' +
certsReference +
ocspReference +
crlsReference +
'>> \n' +
'>>\n';
offsetVri = offsetDss + appendDss.length;
offsets.push(offsetVri);
array = this.insertIntoArray(array, offsetVri, appendVri);
let lastOffset = offsetVri + appendVri.length;
const appendCerts = [];
const appendOcsp = [];
const appendCrls = [];
let offsetDelta = 0;
appendCerts[-1] = '';
for (let i = 0; i < vri.certs.length; i++) {
appendCerts[i] = certsEntry[i] + ' 0 obj\n' +
'<< \n' +
'/Length ' + vri.certs[i].length + ' \n' +
'>>\n' +
'stream\n' +
atob(vri.certs[i]) + '\n' +
'endstream\n' +
'endobj\n';
const currentOffset = lastOffset + appendCerts[i - 1].length;
offsets.push(currentOffset);
array = this.insertIntoArray(array, currentOffset, appendCerts[i]);
lastOffset = currentOffset;
offsetDelta += currentOffset;
}
lastOffset = lastOffset + appendCerts[appendCerts.length - 1].length;
appendOcsp[-1] = '';
for (let i = 0; i < vri.OCSPs.length; i++) {
appendOcsp[i] = ocspEntry[i] + ' 0 obj\n' +
'<< \n' +
'/Length ' + vri.OCSPs[i].length + ' \n' +
'>>\n' +
'stream\n' +
atob(vri.OCSPs[i]) + '\n' +
'endstream\n' +
'endobj\n';
const currentOffset = lastOffset + appendOcsp[i - 1].length;
offsets.push(currentOffset);
array = this.insertIntoArray(array, currentOffset, appendOcsp[i]);
lastOffset = currentOffset;
offsetDelta += currentOffset;
}
lastOffset = lastOffset + appendOcsp[appendOcsp.length - 1].length;
appendCrls[-1] = '';
for (let i = 0; i < vri.CRLs.length; i++) {
appendCrls[i] = crlsEntry[i] + ' 0 obj\n' +
'<< \n' +
'/Length ' + vri.CRLs[i].length + ' \n' +
'>>\n' +
'stream\n' +
atob(vri.CRLs[i]) + '\n' +
'endstream\n' +
'endobj\n';
const currentOffset = lastOffset + appendCrls[i - 1].length;
offsets.push(currentOffset);
array = this.insertIntoArray(array, currentOffset, appendCrls[i]);
lastOffset = currentOffset;
offsetDelta += currentOffset;
}
offsetDelta += appendDss.length + appendVri.length;
let middle = '';
offsets.forEach(offset => {
offset = offset + '';
middle += offset.padStart(10, '0') + ' ' + '00000' + ' ' + ' n' + '\n';
});
let xref = '\nxref\n' +
pdfToSign.dssEntry + ' ' + (2 + vri.certs.length + vri.CRLs.length + vri.OCSPs.length) + '\n' +
middle;
const sha256Hex = sha256(array, false);
xref += this.createTrailer(pdf.xref.topDict, array.length, sha256Hex, pdf.xref.entries.length);
array = this.insertIntoArray(array, array.length, xref);
return array;
}
编辑:我按照@mkl 的建议修复了所有问题。Adobe 不再抛出此错误,但我的签名仍被视为 Baseline-T 而不是 Baseline-LTA,可以在此处检查:https ://ec.europa.eu/cefdigital/DSS/webapp-demo/validation
这是新版本的 singed pdf:https ://easyupload.io/i5bs9k