SignedCms.CheckSignature SAP 证书失败

SignedCms.CheckSignature with SAP certificate is failing

这是 的后续。

我正在编写一个由 SAP 服务器调用的外部服务器。 SAP 服务器在传输之前使用证书对 URL 进行签名。在前面的步骤中,SAP 服务器将用于签署 URL 的证书发送到我的服务器。所以我的服务器有 SAP 服务器用于签名的证书。

根据 SAP 文档,我知道以下内容。

  1. 未签名的URL看起来像这样

    http://pswdf009:1080/ContentServer/ContentServer.dll?get&pVersion=0046&contRep=K1&docId=361A524A3ECB5459E0000800099245EC&accessMode=r&authId=pawdf054_BCE_26&expiration=19981104091537

  2. 重要的 QueryString 参数的值被连接起来(按照它们在 QueryString 中出现的相同顺序)以形成“消息”。
    对于给定的 QueryString-Parameters

     ContRep = K1  
     DocId = 361A524A3ECB5459E0000800099245EC  
     AccessMode = r  
     AuthId = pawdf054_BCE_26  
     Expiration = 19981104091537  
    

    生成的“消息”如下所示:

     K1361A524A3ECB5459E0000800099245ECrpawdf054_BCE_2619981104091537
    
  3. “消息”用于计算从中计算出 SecKey 的哈希值。 SAP 使用数字签名标准 (DSS) 根据 PKCS# 对散列值进行数字签名。数字签名附加到名为 SecKey 的参数中的查询字符串。所选过程的 SecKey 长约 500 字节。在 SAP 文档的示例中,为清楚起见,为 secKey 选择了任意值 0x83、0x70、0x21、0x42。

  4. SecKey 是 base64 编码并添加到 URL.

     0x83, 0x70, 0x21, 0x42   gets to    "g3AhQg=="
    

    传输的 URL 看起来像这样

    http://pswdf009:1080/ContentServer/ContentServer.dll?get&pVersion=0046&contRep=K1&docId=361A524A3ECB5459E0000800099245EC&accessMode=r&authId=pawdf054_BCE_26&expiration=19981104091537&secKey=g3AhQg%3D%3D

  5. 当我的服务器收到 URL 我需要检查签名。我通过按照第 2 点中描述的相同方式连接 QueryString 参数来重新创建“消息”。(如 SAP 文档中所述)

    SAP gives this Summary of Technical Information
    Format of digital signature: PKCS#7 "signed data"
    Public key procedure: DSS
    Key length: 512 - 1024 bits
    Public exponent: 2^16 + 1
    Public key format: X.509 v3 certificate MD (message digest) algorithm: MD5 or RIPEMD-160
    The library for checking signatures can be obtained from SAP AG. Because the standard format PKCS#7 was used for the signature, other products can also be used for decoding.

    我收到“散列值不正确”- cms.CheckSignature(certificates, true);

    行的异常
     private void CheckSignature(string secKey, string message, X509Certificate2 cert)
     {
         byte[] signature = Convert.FromBase64String(secKey);
         ContentInfo ci = new ContentInfo(System.Text.Encoding.ASCII.GetBytes(message));
         SignedCms cms = new SignedCms(ci, true);
         X509Certificate2Collection certificates = new X509Certificate2Collection(cert);
         cms.Decode(signature);
         try
         {
             cms.CheckSignature(certificates, true);
         }
         catch(Exception ex)
         {
             log.Error(ex.ToString());
         }  
     }
    

任何人都可以帮忙,或者知道我做错了什么吗?

实际上上面的 CheckSignature 函数是正确的

但是第二个参数 'message' 必须是 URL-encoded。或者更准确地说,连接时必须使用 NOT-URL-DECODED queryString 值。 [SAP 使用相同的拼写 (uppercase/lowercase)]

ContRep = AA  
DocId = 53730C7E18661EDCB1F816798DAA18B2  
AccessMode = r  
AuthId = CN=NPL          (for concatenating 'CN%3DNPL' is used)
Expiration = 20220511173746

将成为消息

AA53730C7E18661EDCB1F816798DAA18B2rCN%3DNPL20220511173746