我正在使用充气城堡,我想生成一个特定的私钥而不是生成的随机密钥。
我想提供自己的私钥,但代码会不断生成随机密钥。有没有办法指定在充气城堡中使用的确切私钥?
我的代码如下。当我检查生成的证书的公钥时,我总是得到不同的值。我需要我指定的值。
主要
var cb = new X509CertBuilder(suppliers, "CN=MandarinAS, OU=Scheme42, O=MandarinAS, C=GB",
CertStrength.Bits1024);
var cert = cb.MakeCertificate(pwd, "CN=Mandarin, OU=CustomerId, OU=Scheme42, O=OrgX, C=GB", 1,keypair);
File.WriteAllBytes("Cert.pfx", cert.Export(X509ContentType.Pkcs12, pwd));
File.WriteAllBytes("Cert.cer", cert.Export(X509ContentType.Cert, pwd));
var store = new X509Store(storeLocation);
store.Open(OpenFlags.ReadOnly);
var myCertificate = new X509Certificate2("Cert.pfx", "password");
if (myCertificate.PrivateKey !
= null)
{
store.Close();
}
//here i debug and compare the public key values myCertificate is always changing
X509CertBuilder.cs
public class X509CertBuilder
{
private const string SignatureAlgorithm = "SHA1WithRSA";
private readonly int _strength;
private readonly CryptoApiRandomGenerator _randomGenerator = new CryptoApiRandomGenerator();
private readonly X509V3CertificateGenerator _certificateGenerator = new X509V3CertificateGenerator();
private readonly SecureRandom _random;
private readonly X509Name _issuer;
private readonly GeneralName[] _generalNames;
public X509CertBuilder(string[] validWithDomainNames, string issuer, CertStrength certStrength)
{
_random = new SecureRandom(_randomGenerator);
_issuer = new X509Name(issuer);
_strength = (int) certStrength;
_generalNames = new GeneralName[validWithDomainNames.Length];
for (var t = 0; t < validWithDomainNames.Length; t++)
{
_generalNames[t] = new GeneralName(new X509Name(validWithDomainNames[t]));
}
}
public X509Certificate2 MakeCertificate(string password, string issuedToDomainName, int validYears, AsymmetricCipherKeyPair mykey=null)
{
_certificateGenerator.Reset();
_certificateGenerator.SetSignatureAlgorithm(SignatureAlgorithm);
var serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue),
_random);
_certificateGenerator.SetSerialNumber(serialNumber);
_certificateGenerator.SetSubjectDN(new X509Name(issuedToDomainName));
_certificateGenerator.SetIssuerDN(_issuer);
var subjectAlternativeNames = new Asn1Encodable[_generalNames.Length + 1];
// first subject alternative name is the same as the subject
subjectAlternativeNames[0] = new GeneralName(new X509Name(issuedToDomainName));
for (var t = 1; t <= _generalNames.Length; t++)
{
subjectAlternativeNames[t] = _generalNames[t - 1];
}
var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames);
_certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName.Id, false,
subjectAlternativeNamesExtension);
_certificateGenerator.SetNotBefore(DateTime.UtcNow.Date);
_certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddYears(validYears));
var keyGenerationParameters = new KeyGenerationParameters(_random, _strength);
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
var subjectKeyPair = keyPairGenerator.GenerateKeyPair();
_certificateGenerator.SetPublicKey(subjectKeyPair.Public);
//Previouse auto key
//var issuerKeyPair = subjectKeyPair;
//My mykey
var issuerKeyPair = mykey;
var certificate = _certificateGenerator.Generate(issuerKeyPair.Private,_random);
var store = new Pkcs12Store();
var friendlyName = certificate.SubjectDN.ToString();
var certificateEntry = new X509CertificateEntry(certificate);
store.SetCertificateEntry(friendlyName, certificateEntry);
store.SetKeyEntry(friendlyName, new AsymmetricKeyEntry(issuerKeyPair.Private), new[] {certificateEntry});
using (var stream = new MemoryStream())
{
store.Save(stream, password.ToCharArray(), _random);
return new X509Certificate2(stream.ToArray(), password,
X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
}
}
}
答案 0 :(得分:0)
编辑:对Java进行了错误的回答。 BouncyCastle C#API不易在线访问,但我相信您所寻找的是X509CertificateParser
如果你有DER格式的公钥,你可以简单地将编码的byte[]
传递给java.security.cert.CertificateFactory.generateCertificate()
,结果你会获得正确的X509Certificate
。
private static X509Certificate formX509Certificate(byte[] encodedCertificate) throws CertificateException {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(encodedCertificate);
return (X509Certificate) cf.generateCertificate(bais);
} catch (CertificateException e) {
logger.error("Error converting the certificate", e);
throw e;
}
}
您对X509CertBuilder
的来电每次都会生成一个新密钥对的新证书。如果您已经生成了密钥对(来自Java代码或OpenSSL等),只需使用编码的证书值来构建证书对象。
如果您只拥有密钥对值但公钥未形成证书,请使用SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
。
/**
* Generates a self-signed {@link X509Certificate} suitable for use as a Certificate Authority.
*
* @param keyPair the {@link KeyPair} to generate the {@link X509Certificate} for
* @param dn the distinguished name to user for the {@link X509Certificate}
* @param signingAlgorithm the signing algorithm to use for the {@link X509Certificate}
* @param certificateDurationDays the duration in days for which the {@link X509Certificate} should be valid
* @return a self-signed {@link X509Certificate} suitable for use as a Certificate Authority
* @throws CertificateException if there is an generating the new certificate
*/
public static X509Certificate generateSelfSignedX509Certificate(KeyPair keyPair, String dn, String signingAlgorithm, int certificateDurationDays)
throws CertificateException {
try {
ContentSigner sigGen = new JcaContentSignerBuilder(signingAlgorithm).setProvider(BouncyCastleProvider.PROVIDER_NAME).build(keyPair.getPrivate());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
Date startDate = new Date();
Date endDate = new Date(startDate.getTime() + TimeUnit.DAYS.toMillis(certificateDurationDays));
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
reverseX500Name(new X500Name(dn)),
getUniqueSerialNumber(),
startDate, endDate,
reverseX500Name(new X500Name(dn)),
subPubKeyInfo);
// Set certificate extensions
// (1) digitalSignature extension
certBuilder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment
| KeyUsage.keyAgreement | KeyUsage.nonRepudiation | KeyUsage.cRLSign | KeyUsage.keyCertSign));
certBuilder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
certBuilder.addExtension(Extension.subjectKeyIdentifier, false, new JcaX509ExtensionUtils().createSubjectKeyIdentifier(keyPair.getPublic()));
certBuilder.addExtension(Extension.authorityKeyIdentifier, false, new JcaX509ExtensionUtils().createAuthorityKeyIdentifier(keyPair.getPublic()));
// (2) extendedKeyUsage extension
certBuilder.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(new KeyPurposeId[]{KeyPurposeId.id_kp_clientAuth, KeyPurposeId.id_kp_serverAuth}));
// Sign the certificate
X509CertificateHolder certificateHolder = certBuilder.build(sigGen);
return new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate(certificateHolder);
} catch (CertIOException | NoSuchAlgorithmException | OperatorCreationException e) {
throw new CertificateException(e);
}
}