在我的工作中,我必须使用中文SM2加密算法对pdf进行签名并验证签名,因此我选择了itext来帮助我的工作。但是由于这是我第一次使用itext lib,因此我不熟悉它。
我使用外部签名的签名部分,将SM2签名放入pdf的签名字典中。我可以在Internet上找到很多与此相关的代码。但是在验证签名时,我几乎找不到帮助(itext不支持SM2算法,这就是为什么我不能使用标准的Verify方法,而必须实现自己的功能来验证SM2签名的原因。我的意思是我不知道如何获取签名的原始数据,就像我在使用“ GetRangeStream”签名部分,我不知道如何从pdf的表单字段中读取SM2签名。
有人可以给我一些帮助吗?非常感谢。
答案 0 :(得分:0)
您显然需要的代码与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();
}
}