我有一个用于测试目的的pfx文件,没有特殊的安全性。
我需要使用此文件来加密XML文件。场景是我需要向客户端发送一个Password-Zip文件以及与Zip相关的元数据文件。 Zip实际上包含用于更新软件安装的文件。起初,我虽然加密了Zip本身。但后来,决定用简单的密码保护它,并将其上传到客户端的网站(ASP.NET)。客户端还将上载将与Zipped更新一起提供的元数据文件。此元数据文件将包含客户端标识符,MAC地址,MD5哈希更新zip文件等...我需要在发送和解密后加密此元数据文件,一旦客户端上传ZIP和Meta。解密后,我将尝试验证客户端以及当前安装和补丁本身。
为我生成了PFX。
这个问题有点像一个完整的解决方案需求,但我正面临着与X509签约的真正困难时期。我现在正在看BouncyCastle文档。
感谢您的阅读。任何帮助将不胜感激。
答案 0 :(得分: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 ();
这是签署证书签名请求的服务器端发生的情况:
据我所知,根证书可以是您拥有私钥的任何证书。如果您想在浏览器等其他应用程序中使用它,则需要将其插入名为“受信任的根证书颁发机构”的证书存储区(如果它是自签名证书)或“受信任的中间证书颁发机构”(如果它不是在客户端计算机上进行自我签名而不用关键词。
带有私钥的证书可通过添加到图标的小键识别,请参见此处;
//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;