您需要的代码显然类似于 iText 方法 AcroFields.VerifySignature 在创建代表相关签名的 PdfPKCS7 对象时执行的代码。由于 iText 是开源的,您可以根据需要简单地复制该代码!
例如
我不知道如何从 pdf 的表单域中读取 SM2 签名。
AcroFields.VerifySignature 开头是这样的:
virtual public PdfPKCS7 VerifySignature(String name) {
PdfDictionary v = GetSignatureDictionary(name);
if (v == null)
return null;
PdfName sub = v.GetAsName(PdfName.SUBFILTER);
PdfString contents = v.GetAsString(PdfName.CONTENTS);
PdfPKCS7 pk = null;
if (sub.Equals(PdfName.ADBE_X509_RSA_SHA1)) {
PdfString cert = v.GetAsString(PdfName.CERT);
if (cert == null)
cert = v.GetAsArray(PdfName.CERT).GetAsString(0);
pk = new PdfPKCS7(contents.GetOriginalBytes(), cert.GetBytes());
}
else
pk = new PdfPKCS7(contents.GetOriginalBytes(), sub);
因此,提取嵌入签名对象的基本代码是这样的
AcroFields acroFields = reader.AcroFields;
PdfDictionary v = acroFields.GetSignatureDictionary(name);
if (v != null) {
PdfString contents = v.GetAsString(PdfName.CONTENTS);
byte[] embeddedSignatureObjectBytes = contents.GetOriginalBytes();
[... process embeddedSignatureObjectBytes ...]
}
注意:由于 Contents 字符串用零填充,实际签名对象之后的 embeddedSignatureObjectBytes 字节将包含 0x00 字节的尾部。
我不知道如何获取签名的原始数据
AcroFields.VerifySignature 继续这样:
UpdateByteRange(pk, v);
AcroFields.UpdateByteRange 是这样实现的:
private void UpdateByteRange(PdfPKCS7 pkcs7, PdfDictionary v) {
PdfArray b = v.GetAsArray(PdfName.BYTERANGE);
RandomAccessFileOrArray rf = reader.SafeFile;
Stream rg = null;
try {
rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(rf.CreateSourceView(), b.AsLongArray()));
byte[] buf = new byte[8192];
int rd;
while ((rd = rg.Read(buf, 0, buf.Length)) > 0) {
pkcs7.Update(buf, 0, rd);
}
} finally {
if (rg != null) rg.Close();
}
}
因此,读取签名文档字节的基本代码是这样的
AcroFields acroFields = reader.AcroFields;
PdfDictionary v = acroFields.GetSignatureDictionary(name);
if (v != null) {
PdfArray b = v.GetAsArray(PdfName.BYTERANGE);
RandomAccessFileOrArray rf = reader.SafeFile;
Stream rg = null;
try {
rg = new RASInputStream(new RandomAccessSourceFactory().CreateRanged(rf.CreateSourceView(), b.AsLongArray()));
[... process the signed data in the Stream rg ...]
} finally {
if (rg != null) rg.Close();
}
}