如何检查SignedCms信封的签名?

时间:2016-06-20 19:40:12

标签: c# digital-signature x509certificate2 pkcs#7

我真的不懂如何使用PKCS#7消息。

我用一个X509Certificate2签名一些字节数组,并得到一个字节数组。

byte[] data = new byte[5] { 110, 111, 112, 113, 114 }, signedData;

X509Certificate2 cert = new X509Certificate2(certPath, password);

ContentInfo content = new ContentInfo(data);
SignedCms envelope = new SignedCms(content);
CmsSigner cmsSigner = new CmsSigner(cert);
envelope.ComputeSignature(cmsSigner);
signedData = envelope.Encode();

signedData被传输到某个远程接收者,他获得了SignedCms信封。

SignedCms envelope = new SignedCms();
envelope.Decode(signedData);

他如何解码信封?他没有将我的公钥作为参数传递。在信封中有我的公钥,在SignerInfo属性中,但有没有任何理由,因为任何人都可以用整个签名替换它?

收件人可以使用我的公钥确保信封的实际发件人是我吗?

方法envelope.CheckSignature(new X509Certificate2Collection(certificate), true);,但我尝试使用错误的证书,并且没有抛出异常。

2 个答案:

答案 0 :(得分:0)

PKCS#7本身只是一个签名,它可以被替换吗?当然。 envelope.CheckSiganture只是验证pkcs#7具有正确的格式和长度,换句话说,检查pkcs#7是否构造良好。

广泛推荐,您需要实施PKI(私钥基础结构)。在一端,您使用公钥构建您的pkcs#7,另一方面,您必须验证您拥有的pkcs#7实际上是否有您认可的有效证书。您必须实施OCSP来验证这些证书,如果一切都检查完毕,您应该并且必须向第三方请求时间戳以保证您的pkcs#7。你还需要一个保险库(数据库)来跟踪所有事情:pkcs#7,数据哈希,时间戳,原始数据,ocsp响应......

但是如果您只想知道如何识别pkcs#7,可以使用各种工具来解码PKCS#7,此操作会返回其中包含的所有信息。或者您可以使用c#创建自己的。

答案 1 :(得分:0)

PKCS#7 / CMS / S / MIME签名消息是一个数据容器,除了一些其他元数据外还有:

EncapsulatedContentInfo
  ContentInfoType
  EncapsulatedContent (the message bytes)
Certificates (Optional)
CRLs (Optional)
SignerInfos
  DigestAlgorithm (e.g. SHA-1)
  SignedAttributes (Optional, allows other context information to be signed)
  SignatureAlgorithm (e.g. RSA, DSA, ECDSA)
  SignatureValue (the signature bytes)
  UnsignedAttributes (Optional, allows for after-signing information, like counter-signatures)

(这是RFC 2630 (Cryptographic Message Syntax) Section 5

的摘要

SignedCms.Decode读取编码的消息并填充成员。消息的每个直接签名都可以从SignedCms :: SignerInfos属性中读取(反签名者,或已经签名的实体,他们目睹了原始签名,可以从SignerInfo :: CounterSignerInfos中读取)。

当您调用SignedCms.CheckSignature时,它会检查每个SigerInfo并验证签名是否可以成功验证(或抛出异常),以及每个反签名者签名都可以解决。

它不知道的是,任何签名者“都有道理”。对于该检查,您需要遍历每个SignerInfo并查看(例如)Certificate属性;然后进行适用性检查:

  • 也许是预先注册的公钥
  • 也许它链接到一个众所周知的根或中间CA
  • 也许它有某种扩展,表明它是合适的

这部分SignedCms无法为您实际做,因为与TLS的主机名验证不同,消息没有“适合”的默认概念。

如果要评估单个签名者的签名,可以调用SignedInfo :: CheckSignature,但如果您还调用了SignedCms :: CheckSignature,则这是多余的。

  

方法envelope.CheckSignature(new X509Certificate2Collection(certificate),true);但我试图使用错误的证书,并没有抛出异常。

extraCerts重载提供额外证书。有一个SignedCms消息没有嵌入签名者证书是有效的,让接收者提前知道有效证书(例如使用预先注册证书的每用户数据库)。您没有收到异常,因为在提供的证书集合中找到了正确的证书。

您可以通过X509Certificate2Collection.Import方法查看提供的证书集合中的内容;他们可以读取PKCS#7签名数据消息,并使用可选的嵌入式证书填充该集合。