Itext 智能卡上的外部签名
我使用的智能卡对文档的SHA-1哈希进行签名,并计算256字节的数字签名 我正在使用这个问题上发布的代码- 我的问题是,我得到了一个错误:“自从应用签名以来,文档已被修改或损坏” 我正在使用GUI创建哈希,然后将卡上计算的签名256字节发送给签名函数 这是我的密码: filepath pdf文档的哈希创建代码: 上面的代码用于其中一个GUI函数来创建文档的哈希Itext 智能卡上的外部签名,itext,digital-signature,smartcard,Itext,Digital Signature,Smartcard,我使用的智能卡对文档的SHA-1哈希进行签名,并计算256字节的数字签名 我正在使用这个问题上发布的代码- 我的问题是,我得到了一个错误:“自从应用签名以来,文档已被修改或损坏” 我正在使用GUI创建哈希,然后将卡上计算的签名256字节发送给签名函数 这是我的密码: filepath pdf文档的哈希创建代码: 上面的代码用于其中一个GUI函数来创建文档的哈希 namespace EIDSmartCardSign { class PdfSignature { pr
namespace EIDSmartCardSign
{
class PdfSignature
{
private string outputPdfPath;
private string certPath;
byte[] messageDigest;
private string inputPdfPath;
public PdfSignature(byte[] messageDigest, string inputPdfPath,string outputPdfPath)
{
this.messageDigest = messageDigest;
this.outputPdfPath = outputPdfPath;
this.inputPdfPath = inputPdfPath;
}
public void setCertPath(string certPath)
{
this.certPath = certPath;
}
public void signPdf()
{
X509Certificate2 cert = new X509Certificate2();
cert.Import(certPath); // .cer file certificate obtained from smart card
X509CertificateParser certParse = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[1] ;
chain[0] = certParse.ReadCertificate(cert.RawData);
X509Certificate2[] certs;
PdfReader reader = new PdfReader(inputPdfPath);
FileStream fout = new FileStream(outputPdfPath,FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, fout, '\0',null,true);
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SignatureCreator = "Me";
appearance.Reason = "Testing iText";
appearance.Location = "On my Laptop";
iTextSharp.text.Rectangle rec = new iTextSharp.text.Rectangle(50, 50, 250, 100);
appearance.SetVisibleSignature(rec, 1, "Signature");
IExternalSignature extSignature= new MyExternalSignature("SHA-1",this.messageDigest);
MakeSignature.SignDetached(appearance, extSignature, chain, null, null, null, 0, CryptoStandard.CMS);
//MakeSignature.
}
}
}
您的散列创建函数
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
SHA256 sha2 = SHA256.Create();
//sha2.ComputeHash
byte[] pdfBytes = System.IO.File.ReadAllBytes(filePath);
byte[] hash = null;
hash = sha1.ComputeHash(pdfBytes);
计算错误的哈希值
看一看关于信息安全栈交换的,特别是草图
显示要获得要签名的文档字节,您不需要原始PDF,而是必须为集成签名容器做好准备(添加签名字段、字段值以及为签名容器保留的一些空间和字段可视化)然后散列除为签名容器保留的空间之外的所有字节
此外,即使这个裸散列也不是要签名的数据。而是构建一组属性,其中一个包含如上所述计算的文档散列,另一个包含对签名者证书等的引用,这些属性将被签名
因此,要做你已经声称要做的事情:
我正在使用这个问题上发布的代码-
特别地,那里的代码没有对整个文件的散列进行签名,而是使用IExternalSignature
实现的sign
方法接收的数据作为参数,该参数如上所述构造
更多细节
OP在评论中说
我正在使用的卡需要一个20字节的散列
SHA1或RIPEMD-160生成的裸散列通常为20字节。根据您的问题文本,我假设使用了前一种算法。(顺便说一句,这表明上下文不需要高安全级别,因为SHA1实际上已经被淘汰或正在被淘汰。)
在对pdf内容进行散列后,需要采取哪些步骤来进一步创建此散列
只需按照您提到的问题中的IExternalSignature
实现执行即可:
public virtual byte[] Sign(byte[] message) {
byte[] hash = null;
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
hash = sha1.ComputeHash(message);
}
byte[] sig = MySC.GetSignature(hash);
return sig;
}
(很明显,您的智能卡签名例程没有被调用MySC.GetSignature
,您必须相应地替换该调用…)
因为你的卡片看起来期望一个裸哈希值,而不是参考问题OP的卡片,这应该适合你
在哪里可以找到创建上述集成签名容器的示例
在iText白皮书的示例中
在签名过程之后,我有256字节的签名数据,3.cer证书从卡中导出
256字节的签名数据听起来像是使用密钥大小为2048位的RSA或RSASSA-PSS生成的裸签名
也就是说,在签名之前需要签名者证书:在大多数相关的配置文件中,签名的属性必须包含对签名者证书的引用。在问题中提到的代码中,签名者证书在此处处理
public void StartTest(){
X509Certificate2 cert = new X509Certificate2();
cert.Import("cert.cer"); // certificate obtained from smart card
X509CertificateParser certParse = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { certParse.ReadCertificate(cert.RawData) };
[...]
MyMakeSignature.SignDetached(appearance, externalSignature, chain, null, null, tsc, 0, CryptoStandard.CADES);
特别是,您必须在您的卡返回的三个证书中确定正确的签名者证书;否则,您可能会遇到与引用问题中OP相同的问题
当我拥有所有这些数据时,如何创建Contents对象
考虑到您所说的用例,很有可能您真的只需要对问题的代码稍加修改即可。您的哈希创建函数
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
SHA256 sha2 = SHA256.Create();
//sha2.ComputeHash
byte[] pdfBytes = System.IO.File.ReadAllBytes(filePath);
byte[] hash = null;
hash = sha1.ComputeHash(pdfBytes);
计算错误的哈希值
看一看关于信息安全栈交换的,特别是草图
显示要获得要签名的文档字节,您不需要原始PDF,而是必须为集成签名容器做好准备(添加签名字段、字段值以及为签名容器保留的一些空间和字段可视化)然后散列除为签名容器保留的空间之外的所有字节
此外,即使这个裸散列也不是要签名的数据。而是构建一组属性,其中一个包含如上所述计算的文档散列,另一个包含对签名者证书等的引用,这些属性将被签名
因此,要做你已经声称要做的事情:
我正在使用这个问题上发布的代码-
特别地,那里的代码没有对整个文件的散列进行签名,而是使用IExternalSignature
实现的sign
方法接收的数据作为参数,该参数如上所述构造
更多细节
OP在评论中说
我正在使用的卡需要一个20字节的散列
SHA1或RIPEMD-160生成的裸散列通常为20字节。根据您的问题文本,我假设使用了前一种算法。(顺便说一句,这表明上下文不需要高安全级别,因为SHA1实际上已经被淘汰或正在被淘汰。)
在对pdf内容进行散列后,需要采取哪些步骤来进一步创建此散列
只需按照您提到的问题中的IExternalSignature
实现执行即可:
public virtual byte[] Sign(byte[] message) {
byte[] hash = null;
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
hash = sha1.ComputeHash(message);
}
byte[] sig = MySC.GetSignature(hash);
return sig;
}
(很明显,您的智能卡签名例程没有被调用MySC.GetSignature
,您必须相应地替换该调用…)
因为你的卡片看起来期望一个裸哈希值,而不是参考问题OP的卡片,这应该适合你
在哪里可以找到创建上述整数的示例