C#-从PDF签名中获取公钥

C#-从PDF签名中获取公钥,c#,pdf,ssl,certificate,C#,Pdf,Ssl,Certificate,用例如下所示: 用户进入需要出示证书的网站 如果有效,用户可以下载PDF并使用相同的证书签名 上传PDF文件 服务器验证PDF是否由提供给网站的同一证书签名 我被困在第四步。我已经设法从网站和PDF中获取了客户端证书公钥,但它们并不相同。公钥是2048位的SHA256 RSA。此外,我正在使用iTextSharp处理PDF文档 这是我的密码: HttpRequest request = context.Request; HttpClientCertificate cert = reques

用例如下所示:

  • 用户进入需要出示证书的网站
  • 如果有效,用户可以下载PDF并使用相同的证书签名
  • 上传PDF文件
  • 服务器验证PDF是否由提供给网站的同一证书签名
  • 我被困在第四步。我已经设法从网站和PDF中获取了客户端证书公钥,但它们并不相同。公钥是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("-", " ");
     }
    
    HttpRequest-request=context.request;
    HttpClientCertificate cert=request.ClientCertificate;
    //从客户端证书获取公钥
    字符串certKey=BitConverter.ToString(cert.PublicKey)。替换(“-”,“”)
    //现在获取PDF并检索公钥
    PdfReader PdfReader=新PdfReader(“路径到pdf”);
    AcroFields=pdfreader.AcroFields;
    AcroFields.Item Item=fields.GetFieldItem(“签名1”);
    列表名称=字段。GetSignatureNames();
    foreach(名称中的字符串名称){
    PdfDictionary dict=fields.GetSignatureDictionary(名称);
    PdfPKCS7 pkcs7=字段。验证签名(名称);
    Org.bounchycastle.X509.X509Certificate cert=pkcs7.SigningCertificate;
    //从PDF证书获取公钥
    SubjectPublicKeyInfo publicKeyInfo=SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(证书GetPublicKey());
    字节[]serializedPublicBytes=publicKeyInfo.ToAsn1Object().GetDeRecoded();
    string serializedPublic=BitConverter.ToString(serializedPublicBytes)。替换(“-”,”);
    }
    

    使用此代码时,certKey和serializedPublic不相同。

    在代码中比较

    • 证书(
      HttpClientCertificate.PublicKey
      )中的公钥二进制值
    • SubjectPublicKeyInfo
      对象(
      publicKeyInfo.ToAsn1Object().GetDerEncoded()
      )的二进制值,用于包装公钥及其算法
    因此,后者可能会包含前者,但不会与前者一致

    SubjectPublicKeyInfo
    的定义如下:

    SubjectPublicKeyInfo ::= SEQUENCE {
        algorithm AlgorithmIdentifier,
        publicKey BIT STRING
    }
    
    因此,您应该与包含的公钥的二进制表示进行比较,而不是与完整的
    SubjectPublicKeyInfo
    对象的二进制表示进行比较:

    publicKeyInfo.PublicKeyData.GetBytes()
    

    它们是根本不同的(关于字节序列部分的长度和整体相似性),还是仅仅是DER/base64编码不匹配?另外,当您使用操作系统或PDF viewer的证书属性对话框查看这两个证书时,它们是否匹配?我没有想到这一点。我的代码是从PDF中获取的,与我可以直接从查看器的证书属性中看到的相同,与从证书中获取的不同我不会怀疑浏览器/iis往返会造成混乱。。。然后我们应该先找出差异在哪里变得明显。我想你有某种自我签名的测试证书吧?签名PDF中显示的公钥是否与原始证书的公钥匹配?@A77ak您似乎将证书(
    HttpClientCertificate.PublicKey
    )中的公钥二进制值与
    SubjectPublicKeyInfo
    对象(
    publicKeyInfo.ToAsn1Object().GetDeRecoded()的二进制值进行比较
    ),它包装公钥及其算法。因此,后者可能会包含前者,但不会与前者一致。您可能需要尝试
    publicKeyInfo.PublicKeyData.GetBytes()
    instead@mkl它起作用了!非常感谢。