关于C#:从pdf签名中获取公钥

C# - Get public key from PDF Signature

用例如下:

  • 用户进入需要出示证书的网站
  • 如果有效,用户可以下载PDF并使用相同的证书对其进行签名。
  • 上传PDF文件
  • 服务器验证PDF是否由提供给网站的同一证书签名。
  • 我被困在第四步。我已经设法从网站和pdf中获取了客户证书公钥,但两者并不相同。公钥是一个2048位的sha256 rsa。另外,我正在使用ITextSharp处理PDF文档。

    这是我的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     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中的公钥二进制值
    • 包含公钥及其算法的SubjectPublicKeyInfo对象(publicKeyInfo.ToAsn1Object().GetDerEncoded()对象)的二进制值。

    因此,后者可能包含前者,但与前者不一致。

    SubjectPublicKeyInfo的定义如下:

    1
    2
    3
    4
    SubjectPublicKeyInfo ::= SEQUENCE {
        algorithm AlgorithmIdentifier,
        publicKey BIT STRING
    }

    因此,您不必与完整SubjectPublicKeyInfo对象的二进制表示进行比较,而应该与包含的公钥的二进制表示进行比较:

    1
    publicKeyInfo.PublicKeyData.GetBytes()