【问题标题】:Use a PFX File X509 for Encrypt/Decrypt使用 PFX 文件 X509 进行加密/解密
【发布时间】:2012-07-11 08:04:22
【问题描述】:

我有一个用于测试目的的 pfx 文件,没有特殊的安全性。

我需要使用这个文件来加密一个 XML 文件。场景是我需要将 Password-Zip 文件连同与 Zip 相关的元数据文件发送给客户端。 Zip 实际上包含用于更新软件安装的文件。起初,我虽然会加密 Zip 本身。但是后来,决定用一个简单的密码保护它,并将其上传到客户端的网站(ASP.NET)。客户端还将上传一个元数据文件,该文件将与压缩更新一起提供。此元数据文件将包含客户端标识符、MAC 地址、更新 zip 文件的 MD5 哈希等内容……我需要在客户端上传 ZIP 和 Meta 后在发送和解密之前加密此元数据文件。解密后,我将尝试验证客户端和当前安装以及补丁本身。

PFX 是为我生成的。

  • 我需要从 PFX 中提取什么
  • 我可以在这里使用 BouncyCastle。
  • 这个想法是,一旦客户端安装了软件,他就会生成一个 X509 证书请求。这将创建两件事:请求和私钥。客户端将保留私钥并向我们发送请求。我们将验证客户(付款和所有)并为他生成证书并通过电子邮件将他发回(PFX)。然后,他将导入它以解锁软件的功能,并能够获得压缩更新和其他内容

这个问题有点像一个完整的解决方案需求,但我正面临着一个真正的困难时期,那就是与 X509 签约。我现在正在查看 BouncyCastle 文档。

感谢您的阅读。任何帮助将不胜感激。

【问题讨论】:

    标签: c# bouncycastle x509


    【解决方案1】:

    抱歉,答案很长。

    是的,您可以使用 bouncycastle 从 pfx 中提取证书。

    var pkcs = new Pkcs12Store(File.Open("path.pfx", FileMode.Open), "password".ToCharArray());
    pkcs.Aliases // is a list of certificate names that are in the pfx;
    pkcs.GetCertificate(alias); // gets a certificate from the pfx
    

    我们使用非常相似的方法,但我们将没有私钥的证书发送回 PEM,因为它不包含任何“秘密”

    这是您提出证书签名请求的方式:

    //generate a privatekey and public key
    RsaKeyPairGenerator rkpg1 = new RsaKeyPairGenerator();
    rkpg1.Init(new KeyGenerationParameters(new SecureRandom(), Keystrength));
    AsymmetricCipherKeyPair ackp1 = rkpg1.GenerateKeyPair();
    
    RsaPrivateCrtKeyParameters privateKey = (RsaPrivateCrtKeyParameters)ackp1.Private;
    RsaKeyParameters publicKey = (RsaKeyParameters)ackp1.Public;
    
    X509Name comonname = new X509Name (cname);
    Pkcs10CertificationRequest csr = new Pkcs10CertificationRequest ("SHA1WITHRSA", comonname, publicKey, null, privateKey);
    csr.Verify ();
    
    StringBuilder sb = new StringBuilder();
    PemWriter pw = new PemWriter (new StringWriter (sb));
    pw.WriteObject (csr);
    pw.Writer.Flush ();
    var pemstring = sb.ToString ();
    

    这是在服务器端签署证书签名请求时发生的情况:

    据我了解,根证书可以是您拥有私钥的任何证书。如果您想在其他应用程序(如浏览器)中使用它,则需要将其插入到名为“受信任的根证书颁发机构”的证书存储中,如果它是自签名证书,或者“受信任的中间证书颁发机构”,如果它不是不能在客户端计算机上进行自签名当然没有私人密钥。

    带有私钥的证书可以通过添加到图标的小密钥来识别,请参见此处;

    //rootCert contains the rootcertificate in bouncycastle format
    
    var pemstring = "a string containing the PEM";
    PemReader pr = new PemReader (new StringReader (pemstring));
    Pkcs10CertificationRequest csr = (Pkcs10CertificationRequest)pr.ReadObject ();
    
    X509V3CertificateGenerator certgen = new X509V3CertificateGenerator();
    certgen.SetSubjectDN(csr.GetCertificationRequestInfo().Subject);
    certgen.SetIssuerDN(rootCert.SubjectDN);
    certgen.SetPublicKey(csr.GetPublicKey());
    certgen.SetSignatureAlgorithm(csr.SignatureAlgorithm.ObjectID.Id);
    certgen.SetNotAfter(validThrough); //a datetime object
    certgen.SetNotBefore(validFrom); //a datetime object
    certgen.SetSerialNumber(serialNumber); //a biginteger
    
    X509Certificate clientcert = certgen.Generate(rootPrivateKey);
    
    //to send the certificate without the private key to the client you'll have to 
    //convert it to PEM:
    
    StringBuilder sb = new StringBuilder();
    PemWriter pw = new PemWriter (new StringWriter (sb));
    pw.WriteObject (clientcert);
    pw.Writer.Flush ();
    var pemstring = sb.ToString ();
    
    //to make it a .net certificate use:
    X509Certificate2 netcert = DotNetUtilities.ToX509Certificate (clientcert);
    

    客户端证书不包含私钥 atm。这就是在客户端再次发生的情况:

    //where pemstring contains the certificate in a PEMstring like shown above.
    //and privateKey is the one we had in the first part over at the client.
    
    PemReader pr = new PemReader(new StringReader(pemstring));
    X509Certificate2 cert = DotNetUtilities.ToX509Certificate((Bouncy.X509Certificate)pr.ReadObject());
    
    CspParameters cparms = new CspParameters
    {
        CryptoKeySecurity = new CryptoKeySecurity(),
        Flags = CspProviderFlags.UseMachineKeyStore
    };
    
    RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider(cparms);
    RSAParameters parms = new RSAParameters
    {
        Modulus = privateKey.Modulus.ToByteArrayUnsigned (),
        P = privateKey.P.ToByteArrayUnsigned (),
        Q = privateKey.Q.ToByteArrayUnsigned (),
        DP = privateKey.DP.ToByteArrayUnsigned (),
        DQ = privateKey.DQ.ToByteArrayUnsigned (),
        InverseQ = privateKey.QInv.ToByteArrayUnsigned (),
        D = privateKey.Exponent.ToByteArrayUnsigned (),
        Exponent = privateKey.PublicExponent.ToByteArrayUnsigned ()
    };
    
    rcsp.ImportParameters(parms);
    
    netcert.PrivateKey = rcsp;
    

    【讨论】:

    • 为什么,非常感谢!我会尽我所能,看看这一切如何适合我的场景。在任何地方都找不到如此生动(实际上是代码)描述的整个过程!
    • 希望它有所帮助 :) 如果它确实不要忘记将其标记为答案。
    • 会做...还在想办法。
    • 是的,rootcertificate 是受信任的根证书颁发机构。我已经稍微编辑了这个问题。
    • 我怀疑您的证书存储中是否有带有私钥的证书。但如果是这样,图标的左上角应该有一个小键。您从老板那里得到的 pfx 可能还包含带有私钥的证书。您可以使用工具 makecert 来制作私钥。谷歌它很容易。或在这里查看:msdn.microsoft.com/en-us/library/ms733813.aspx
    猜你喜欢
    • 2020-07-14
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多