2

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

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

PFX 是为我生成的。

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

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

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

4

1 回答 1

4

很长的答案。

是的,您可以使用 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 ();

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

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

带有私钥的证书可以通过添加到图标的小密钥来识别,请参见此处;具有共同名称 localhost 的自签名证书

//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;
于 2012-07-11T09:07:55.893 回答