Для одного из моих приложений (сервер данных OPC UA) я создаю самозаверяющий сертификат.Я должен сгенерировать один для каждой конфигурации.
Вот код для генерации:
public static X509Certificate2 GenerateCertificate(string name, string applicationUri)
{
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), RANDOM);
certificateGenerator.SetSerialNumber(serialNumber);
X509Name x509Name = new X509Name($"C=XX, O=YYYYY, OU=ZZZZ, CN={name}");
certificateGenerator.SetIssuerDN(x509Name);
certificateGenerator.SetSubjectDN(x509Name);
certificateGenerator.SetNotBefore(DateTime.UtcNow.Date.AddDays(-1));
certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddYears(CERTIFICATE_VALIDATE_YEARS));
certificateGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false,
new GeneralNames(new GeneralName[]
{
new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri),
new GeneralName(GeneralName.DnsName, Dns.GetHostName())
}));
certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth, KeyPurposeID.IdKPClientAuth));
certificateGenerator.AddExtension(X509Extensions.KeyUsage, true,
new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment | KeyUsage.DataEncipherment | KeyUsage.KeyCertSign));
KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(RANDOM, STRENGTH);
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
Asn1SignatureFactory signatureFactory = new Asn1SignatureFactory(SIGNATURE_ALGORITHM, issuerKeyPair.Private);
X509Certificate bouncyCert = certificateGenerator.Generate(signatureFactory);
X509Certificate2 certificate;
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
store.SetKeyEntry(name, new AsymmetricKeyEntry(subjectKeyPair.Private), new[] {new X509CertificateEntry(bouncyCert)});
string certificateUniqueId = Guid.NewGuid().ToString("x");
using (MemoryStream ms = new MemoryStream())
{
store.Save(ms, certificateUniqueId.ToCharArray(), RANDOM);
certificate = new X509Certificate2(ms.ToArray(), certificateUniqueId, X509KeyStorageFlags.Exportable);
}
return certificate;
}
Когда я генерирую сертификат, сохраняю и использую его, все работаетхорошо, но если сертификат уже существует, я извлекаю его для его использования.
Вот как я его извлекаю:
public static X509Certificate2 GetOrCreateCertificate(string serverName, string applicationUri)
{
using (X509Store store = new X509Store(OPC_UA_STORE_NAME, StoreLocation.LocalMachine))
{
X509Certificate2 certificate;
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection certificateCollection = store.Certificates.Find(X509FindType.FindBySubjectName, serverName, true);
if (certificateCollection.Count > 0)
{
certificate = certificateCollection[0];
_logger.Information("Using certificate " + serverName + " found in the store: " + certificate + ". Valid: " + (certificate.Verify() ? "True" : "False"));
return certificate;
}
certificate = GenerateCertificate(serverName, applicationUri);
_logger.Information("No valid certificate found for " + serverName + ". Building a new one: " + certificate);
store.Add(certificate);
using (X509Store rootStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
{
using (X509Certificate2 withoutPrivateKey = new X509Certificate2(certificate.RawData))
{
rootStore.Open(OpenFlags.ReadWrite);
rootStore.Add(withoutPrivateKey);
}
}
return certificate;
}
}
В этом случае я получаю ошибку:
И тогда мой сервер OPC UA недействителен в сети (я полагаю, по той же причине, но никаких доказательств этого).
Есть идеи, почему я получаю это MS Event?