如何创建一个pkcs7块只用于密钥交换(充气城堡)

时间:2011-07-03 05:11:56

标签: c# rsa bouncycastle pkcs#7

我正在尝试创建一个包含pkcs 7块的文件。在这个容器中,我需要我的公钥和我的签名者信息(没有签名数据!!!)。我已经尝试了几种没有运气的替代品。这是我的代码:

首先是签名信息:

 List<X509Certificate> certs = new List<X509Certificate> { cert };
 IX509Store x509Certs = X509StoreFactory.Create(
      "CERTIFICATE/COLLECTION",
      new X509CollectionStoreParameters(certs));

 var ias = new IssuerAndSerialNumber(cert.IssuerDN, cert.SerialNumber);
 SignerIdentifier sid = new SignerIdentifier(ias);
 AlgorithmIdentifier algoDigId = new AlgorithmIdentifierCmsSignedGenerator.DigestSha1);
 AlgorithmIdentifier algoCryptId = new AlgorithmIdentifier(CmsSignedGenerator.EncryptionRsa);

 SignerInfo si = new SignerInfo(sid, algoDigId, null, algoCryptId,
                                      new DerOctetString(contentSignature), null);

contentSignature byte []包含一些信息的签名摘要。

现在,当我尝试创建SignedData时,一切都会失效

  var signedContent = new ContentInfo(CmsObjectIdentifiers.Data, DerNull.Instance);
  CmsSignedData csd = new CmsSignedData(signedContent);

我不是要发送信息,这仅用于密钥交换和验证目的。我相信这是一个有效的场景,但不知怎的,这不起作用。

感谢您的帮助。

更新:

更多背景。

我正在尝试从.Net可执行文件中签名JAR。我已完成剩余的过程,但jarsigner创建了一个pkcs7文件:

  • ContentInfo设置为“数据”而没有内容。到目前为止,制作新的ContentInfo(CmsObjectIdentifiers.Data,null)只会在将内容信息添加到CmsData时抛出异常

  • 添加了SignerInfo,此SignerInfo包含先前从JAR内容派生的签名。

2 个答案:

答案 0 :(得分:1)

由于此问题与签署APK / JAR文件有关,我将在该背景下回答。

假设:

您已执行以下所有设置步骤:

  1. 生成有效的MANIFEST.MF
  2. 生成有效的CERT.SF
  3. 将有效的PFX文件加载到名为“cert”
  4. 的X509Certificate2变量中
  5. 将CERT.SF文件的二进制内容放在名为“manifestSFBytes”的字节数组中
  6. 以下代码将生成有效的分离pkcs7签名,这有效地是您的CERT.RSA内容:

    string OID_DATA = "1.2.840.113549.1.7.1";
    
    // setup the data to sign
    ContentInfo content = new ContentInfo( new Oid( OID_DATA ), manifestSFBytes );
    SignedCms signedCms = new SignedCms( content, true );
    CmsSigner signer = new CmsSigner( SubjectIdentifierType.IssuerAndSerialNumber, cert );
    
    // create the signature
    signedCms.ComputeSignature( signer );
    byte[] data = signedCms.Encode();
    

    此代码依赖于System.Security.Cryptography.Pkcs命名空间,不需要BouncyCastle。

    这里发生的是原始内容(签名文件二进制数据)通过ComputeSignature()调用一次性进行哈希和签名。

    因此,不需要“null ContentInfo”技巧,即ContentInfo包含要签名和散列的原始数据,这与Java实现不同,后者在PKCS7生成之前对内容进行签名和散列。

    HTH

    - (e)中

答案 1 :(得分:0)

以下是我认为您想要做的一个简单示例。注意:下面的代码是针对Java bouncycastle的,但我认为这些类在库的C#版本中非常相似。

import java.io.*;
import java.security.cert.*;
import java.util.ArrayList;
import java.util.List;

import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.*;

public class PKCS7CertList1
{

    public static byte[] buildCMSCertThingy() throws Exception
    {
        final List<X509Certificate> certs = new ArrayList<X509Certificate>();
        final InputStream certIs = new FileInputStream("google_com.p7b");
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        for (Certificate cert : cf.generateCertificates(certIs))
        {
            certs.add((X509Certificate) cert);
        }
        certIs.close();
        System.err.printf("Number of certs parsed = %d%n", certs.size());
        final CMSSignedDataGenerator cmsGen = new CMSSignedDataGenerator();
        cmsGen.addCertificates(new JcaCertStore(certs));
        final CMSSignedData sigData = cmsGen.generate(new CMSAbsentContent(), false);
        return sigData.getEncoded();
    }
    public static void main(String[] args) throws Exception
    {   
        FileOutputStream fos = new FileOutputStream("signed_data.der");
        fos.write(buildCMSCertThingy());
        fos.close();
    }

}