我已经研究了所有类似的问题,但找不到一个应用itextsharp延迟签名的案例。
基本上,我的应用程序使用pkcs#7
签名对pdf文档进行签名,该签名是由远程web服务创建的。
我的应用程序向这个web服务发送原始文档的哈希(添加空签名字段后可签名字节的哈希),并接收一个Base64编码的签名文件。
我将此签名嵌入到先前生成的临时pdf文件中,该文件具有空签名字段。
最后,我的签名未被验证,因为Adobe Reader指出文档已更改或已损坏。
添加空签名字段并获得Pdf可签名字节的代码
public static string GetBytesToSign(string unsignedPdf, string tempPdf, string signatureFieldName)
{
if (File.Exists(tempPdf))
File.Delete(tempPdf);
using (PdfReader reader = new PdfReader(unsignedPdf))
{
using (FileStream os = File.OpenWrite(tempPdf))
{
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(new Rectangle(36, 748, 250, 400), 1, signatureFieldName);
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
MakeSignature.SignExternalContainer(appearance, external, 8192);
byte[] array = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());
return Convert.ToBase64String(array);
}
}
}
打开临时Pdf并嵌入接收到的签名的代码
public static void EmbedSignature(string tempPdf, string signedPdf, string signatureFieldName, string signature)
{
byte[] signedBytes = Convert.FromBase64String(signature);
using (PdfReader reader = new PdfReader(tempPdf))
{
using (FileStream os = File.OpenWrite(signedPdf))
{
IExternalSignatureContainer external = new MyExternalSignatureContainer(signedBytes);
MakeSignature.SignDeferred(reader, signatureFieldName, os, external);
}
}
}
此操作的结果是生成最终的signedpdf
。但是,Adobe表示,由于更改或损坏,签名无效。
我的原始文件
Z9QIYVTP4CRBZ1SSCQ+P0JVRINZ5LVJYJXK3L7YP/IE=
我从web服务收到的签名是:
MIIJHAYJKoZIhvcNAQcCoIIJDTCCCQkCAQExCzAJBgUrDgMCGgUAMDsGCSqGSIb3DQEHAaAuBCx6OXFJeXZ0cDRjUkJaMVNTQ1ErUDBKVlJpbno1bHZqWWpYazNMN1lQL0lFPaCCBqkwggalMIIFjaADAgECAhEAm+WwbUP4/745xTxbwPwWeTANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJUUjEoMCYGA1UECgwfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE2MDQGA1UEAwwtVEVTVCBUdXJrY2VsbCBNb2JpbCBORVMgSGl6bWV0IFNhZ2xheWljaXNpIFMyMB4XDTE3MDgyNTEyNDcyMVoXDTE4MDgyNTEyNDcyMVowSjELMAkGA1UEBhMCVFIxETAPBgNVBAoMCEZpcmUgTExUMRQwEgYDVQQFEws3NjU0MzQ1Njc2NTESMBAGA1UEAwwJTWVydCBJbmFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjlPTM4EEPiLsJvW/zAMvT4HLyLWHZTQcMVDvf+I0GQz0Z3uZRTSLYD3AlN6KS1Ih4FT8kvOpWnu8rznt1mWuVP2qIfZw1C5+H6rYyk2TvC09wMAJV51WQFQ2QiChcHKDhwaYBihYGwPbMNeJle6RK2NRbCz7/EJTSEAMh6UU42vXjXNEeKd1+rzpCsNMLupscG0NPt0lyRbNoM8d/deV6P5T8DXH/yR3nThVloVB8A9gE6AY9j3XwbUeMG2VqNGfKuXXQu5XvTwgdm0CYqYR91k56r//04ZlkuHacnzpvkVrpc8WHHMvH+6AFL/wYe2JVh4k6V8ddGXnDaTZW/+yxQIDAQABo4IDXzCCA1swQgYIKwYBBQUHAQEENjA0MDIGCCsGAQUFBzABhiZodHRwOi8vdGVzdG9jc3AyLmUtZ3V2ZW4uY29tL29jc3AueHVkYTAfBgNVHSMEGDAWgBRP2BJrMB9Cudmu4ir350kVnsT05TCCAXIGA1UdIASCAWkwggFlMIGxBgZghhgDAAEwgaYwNgYIKwYBBQUHAgEWKmh0dHA6Ly93d3cuZS1ndXZlbi5jb20vZG9jdW1lbnRzL05FU1VFLnBkZjBsBggrBgEFBQcCAjBgGl5CdSBzZXJ0aWZpa2EsIDUwNzAgc2F5xLFsxLEgRWxla3Ryb25payDEsG16YSBLYW51bnVuYSBnw7ZyZSBuaXRlbGlrbGkgZWxla3Ryb25payBzZXJ0aWZpa2FkxLFyMIGuBglghhgDAAEBAQMwgaAwNwYIKwYBBQUHAgEWK2h0dHA6Ly93d3cuZS1ndXZlbi5jb20vZG9jdW1lbnRzL01LTkVTSS5wZGYwZQYIKwYBBQUHAgIwWRpXQnUgc2VydGlmaWthLCBNS05FU0kga2Fwc2FtxLFuZGEgeWF5xLFubGFubcSxxZ8gYmlyIG5pdGVsaWtsaSBlbGVrdHJvbmlrIHNlcnRpZmlrYWTEsXIuMF0GA1UdHwRWMFQwUqBQoE6GTGh0dHA6Ly90ZXN0c2lsLmUtZ3V2ZW4uY29tL0VsZWt0cm9uaWtCaWxnaUd1dmVubGlnaUFTTUtORVNJLVMyL0xhdGVzdENSTC5jcmwwDgYDVR0PAQH/BAQDAgbAMIGDBggrBgEFBQcBAwR3MHUwCAYGBACORgEBMGkGC2CGGAE9AAGnTgEBDFpCdSBzZXJ0aWZpa2EsIDUwNzAgc2F5aWxpIEVsZWt0cm9uaWsgSW16YSBLYW51bnVuYSBnw7ZyZSBuaXRlbGlrbGkgZWxla3Ryb25payBzZXJ0aWZpa2FkaXIwUAYDVR0JBEkwRzAUBggrBgEFBQcJAjEIBAZBbmthcmEwHQYIKwYBBQUHCQExERgPMTk3ODEyMzEyMDAwMDBaMBAGCCsGAQUFBwkEMQQEAlRSMBgGA1UdEQQRMA+BDWZpcmVAZmlyZS5jb20wHQYDVR0OBBYEFNhQQlfraWETORktKtN1Ih0T2fwrMA0GCSqGSIb3DQEBCwUAA4IBAQBX8xj9Onuft4bv+1Ylb5eUOAg9ArWcAWC9keb4Oh0MnwGfsI9aa/wQGZw3HHk9gygbvLngTr4rNXKN08G7mjRi1bIqUsqcfVK34S2m06a3b1UUA4ONqVtDQCf3frUPEgNEdsydA5omJFPAyUiEQPlUNrc5NSEGvts2VWSnc3lWzZG6hJ03KlF+rgP9wKlqRW6CwXI+TjOFaQaFNLkOUvtzkpioKdTi6CkLfchEkYHTk9J2MgJ5ftg3SgB2HMX7lBkTB4+OCsNv5E5WldhoZUxYgIDw3a05e6p0NigYDOPVh6ac+qtKfxraLCptacW6PB6nnDkL9MIVVpBZrg0adww7MYICCzCCAgcCAQEwgYQwbzELMAkGA1UEBhMCVFIxKDAmBgNVBAoMH0VsZWt0cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xNjA0BgNVBAMMLVRFU1QgVHVya2NlbGwgTW9iaWwgTkVTIEhpem1ldCBTYWdsYXlpY2lzaSBTMgIRAJvlsG1D+P++OcU8W8D8FnkwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE3MDkyMjEzMTgzOFowIwYJKoZIhvcNAQkEMRYEFO83ODuxMauWzvxHHjKneXNdlRUEMA0GCSqGSIb3DQEBAQUABIIBAHlgXQRztih9IuJW/SedVO/K1yJQfX46jxC9kI+tu6mNJXJaybIQh+lsLV4kU9QpyxMHYyIF+5RQ2HvldpBlBOUMZFbd9g0LD2CJ/Q/1lg/R25x0yim7EjpY+POlm9rfQfVqoQTnd+QkWO1+3d+g2sbJHaFKe/YT2aOp88dFC02Wor9Et71vKHeaxMs47GOet39DXvfI5m2dLX6tCytMwxUSa2002A2PYypstQmd3gU+VMKLfkrWeO8kwTI4uRRAg/bGWYgqeCrwaaOuAmXh80LOh75Ugf0bqeC5rDkJN2Zx9cbnmNUCNkifm2VDpvie1mGmkpOP0MjJ8rx2mZXJs4k=
我比较了tempFile和signedFile的字节,只有tempFile的0(我想是用于临时签名文件)被替换为signedFile中的实际签名。
在您从web服务收到的签名中有:
39 59: . . . SEQUENCE {
41 9: . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
: . . . . . (PKCS #7)
52 46: . . . . [0] {
54 44: . . . . . OCTET STRING
: . . . . . . 7A 39 71 49 79 76 74 70 z9qIyvtp
: . . . . . . 34 63 52 42 5A 31 53 53 4cRBZ1SS
: . . . . . . 43 51 2B 50 30 4A 56 52 CQ+P0JVR
: . . . . . . 69 6E 7A 35 6C 76 6A 59 inz5lvjY
: . . . . . . 6A 58 6B 33 4C 37 59 50 jXk3L7YP
: . . . . . . 2F 49 45 3D /IE=
: . . . . . }
: . . . . }
[...]
1955 9: . . . . . SEQUENCE {
1957 5: . . . . . . OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
: . . . . . . . (OIW)
1964 0: . . . . . . NULL
: . . . . . . }
1966 93: . . . . . [0] {
1968 24: . . . . . . SEQUENCE {
1970 9: . . . . . . . OBJECT IDENTIFIER contentType (1 2 840 113549 1 9 3)
: . . . . . . . . (PKCS #9)
1981 11: . . . . . . . SET {
1983 9: . . . . . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
: . . . . . . . . . (PKCS #7)
: . . . . . . . . }
: . . . . . . . }
1994 28: . . . . . . SEQUENCE {
1996 9: . . . . . . . OBJECT IDENTIFIER signingTime (1 2 840 113549 1 9 5)
: . . . . . . . . (PKCS #9)
2007 15: . . . . . . . SET {
2009 13: . . . . . . . . UTCTime 22/09/2017 13:18:38 GMT
: . . . . . . . . }
: . . . . . . . }
2024 35: . . . . . . SEQUENCE {
2026 9: . . . . . . . OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
: . . . . . . . . (PKCS #9)
2037 22: . . . . . . . SET {
2039 20: . . . . . . . . OCTET STRING
: . . . . . . . . . EF 37 38 3B B1 31 AB 96 .78;.1..
: . . . . . . . . . CE FC 47 1E 32 A7 79 73 ..G.2.ys
: . . . . . . . . . 5D 95 15 04 ]...
: . . . . . . . . }
: . . . . . . . }
: . . . . . . }
2061 13: . . . . . SEQUENCE {
2063 9: . . . . . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
: . . . . . . . (PKCS #1)
2074 0: . . . . . . NULL
: . . . . . . }
在此,您的base64编码散列显示为嵌入的有符号数据(偏移56..99)。此外,哈希算法被选择为“SHA-1”(offsets 1955.1965),并且签名的文档哈希是与SHA-1哈希值的大小匹配的20字节值。此外,如PKCS#1 1.5(偏移量2061.2075)中所述,RSA用于签名。
因此,您的签名服务看起来不是将您的输入用作base64编码的预先计算的文档哈希值,而是用作使用SHA1WITHRSA/2048进行签名的普通数据。
因此错误不在iText使用代码中,而在签名服务调用代码中。
我检查了Stackoverflow上的其他类似问题,但它在我的案例中不起作用。 情境:我正在开发一个需要签署pdf文档的应用程序。签名密钥由另一家公司持有,假设它是Companya。 我做了以下几个步骤: null 然后,将消息摘要发送给CompanyA进行签名。在我从CompanyA获得签名的摘要(它是base64编码的)之后,我调用方法来获得签名的pdf文档。 最后我可以得到签名的pdf文档,
对于一个关于签名数据被哈希两次的C#问题,我看到了一个类似的答复,但是我不知道为什么我的签名数据会出现在这里。 C#PKCS7 Smartchard数字签名损坏
我正在使用PDFbox-1.8.8在PDF文件上做签名功能。 当我签署一份文件的时候 下面是我的代码:
我尝试使用智能卡(USB令牌)对pdf文件进行签名,但在Adobe中打开签名的pdf文件时,遇到错误。这个错误不是描述性的,我也不知道该去哪里看,因为代码对我来说似乎很好,但显然不是… 我使用的代码是: 我尝试签名的pdf文件是这个。 添加签名字段后创建的临时pdf文件如下。 签名的Base64格式为
我试图对pdf文件进行签名,但在Adobe中打开签名的pdf文件时,遇到“文档自签名后已被更改或损坏”错误。 这个错误不是那么描述性的,我不确定应该在哪里查看,因为代码对我来说似乎很好,但显然不是。。 我使用的代码是: 签名的哈希的Base64格式为(tmp文件sha_前缀): 签名(AMA)的Base64格式为: 有人能帮忙吗?