Код, который вам нужен, очевидно, аналогичен коду, который метод iText AcroFields.VerifySignature
выполняет при создании объекта PdfPKCS7
, представляющего данную подпись. Так как iText является открытым исходным кодом, вы можете просто скопировать этот код так, как вам нужно!
* 1005 Е.Г. *
Я не знаю, как прочитать подпись SM2 из поля формы PDF.
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();
}
}