C# - 从 PDF 签名中获取 public 密钥
C# - Get public key from PDF Signature
使用案例如下:
- 用户进入需要出示证书的网站
- 如果有效,用户可以下载 PDF 并使用相同的证书对其进行签名
- 上传 PDF
- 服务器验证 PDF 是由提供给网站的同一证书签名的。
我卡在了第 4 步。我已经设法从网站和 PDF 中获取了客户端证书 public 密钥,但两者并不相同。 public 密钥是 2048 位的 SHA256 RSA。另外,我正在使用 iTextSharp 来处理 PDF 文档。
这是我的代码:
HttpRequest request = context.Request;
HttpClientCertificate cert = request.ClientCertificate;
//get public key from client certificate
string certKey = BitConverter.ToString(cert.PublicKey).Replace("-", " ")
//now gets PDF and retrieves public key
PdfReader pdfreader = new PdfReader("path_to_pdf");
AcroFields fields = pdfreader.AcroFields;
AcroFields.Item item = fields.GetFieldItem("Signature1");
List<string> names = fields.GetSignatureNames();
foreach (string name in names){
PdfDictionary dict = fields.GetSignatureDictionary(name);
PdfPKCS7 pkcs7 = fields.VerifySignature(name);
Org.BouncyCastle.X509.X509Certificate cert = pkcs7.SigningCertificate;
//get public key from PDF cert
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(cert.GetPublicKey());
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPublic = BitConverter.ToString(serializedPublicBytes).Replace("-", " ");
}
使用此代码 certKey 和 serializedPublic 不一样。
在你的代码中比较
- 来自证书 (
HttpClientCertificate.PublicKey
) 的 public 密钥二进制值和
- 包装 public 密钥及其算法的
SubjectPublicKeyInfo
对象 (publicKeyInfo.ToAsn1Object().GetDerEncoded()
) 的二进制值。
因此,后者可能 包含 前者,但 不与前者重合。
一个SubjectPublicKeyInfo
是这样定义的:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
publicKey BIT STRING
}
因此,您应该与包含的 public 键的二进制表示进行比较,而不是与完整 SubjectPublicKeyInfo
对象的二进制表示进行比较:
publicKeyInfo.PublicKeyData.GetBytes()
使用案例如下:
- 用户进入需要出示证书的网站
- 如果有效,用户可以下载 PDF 并使用相同的证书对其进行签名
- 上传 PDF
- 服务器验证 PDF 是由提供给网站的同一证书签名的。
我卡在了第 4 步。我已经设法从网站和 PDF 中获取了客户端证书 public 密钥,但两者并不相同。 public 密钥是 2048 位的 SHA256 RSA。另外,我正在使用 iTextSharp 来处理 PDF 文档。
这是我的代码:
HttpRequest request = context.Request;
HttpClientCertificate cert = request.ClientCertificate;
//get public key from client certificate
string certKey = BitConverter.ToString(cert.PublicKey).Replace("-", " ")
//now gets PDF and retrieves public key
PdfReader pdfreader = new PdfReader("path_to_pdf");
AcroFields fields = pdfreader.AcroFields;
AcroFields.Item item = fields.GetFieldItem("Signature1");
List<string> names = fields.GetSignatureNames();
foreach (string name in names){
PdfDictionary dict = fields.GetSignatureDictionary(name);
PdfPKCS7 pkcs7 = fields.VerifySignature(name);
Org.BouncyCastle.X509.X509Certificate cert = pkcs7.SigningCertificate;
//get public key from PDF cert
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(cert.GetPublicKey());
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string serializedPublic = BitConverter.ToString(serializedPublicBytes).Replace("-", " ");
}
使用此代码 certKey 和 serializedPublic 不一样。
在你的代码中比较
- 来自证书 (
HttpClientCertificate.PublicKey
) 的 public 密钥二进制值和 - 包装 public 密钥及其算法的
SubjectPublicKeyInfo
对象 (publicKeyInfo.ToAsn1Object().GetDerEncoded()
) 的二进制值。
因此,后者可能 包含 前者,但 不与前者重合。
一个SubjectPublicKeyInfo
是这样定义的:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
publicKey BIT STRING
}
因此,您应该与包含的 public 键的二进制表示进行比较,而不是与完整 SubjectPublicKeyInfo
对象的二进制表示进行比较:
publicKeyInfo.PublicKeyData.GetBytes()