Disclaimer: I am 2 days into reading about Certificates/RSA Algorithms and Encrypt/Decrypt.
I am trying to do a small app that communicates with Windows Key Store ( Certificate Store ) and where I should be able to read certificates/add certificates.
I have created a method to add a certificate.
public void AddKey()
{
CngKey cngKey;
CngKeyCreationParameters cng = new CngKeyCreationParameters
{
KeyUsage = CngKeyUsages.AllUsages
};
if (!CngKey.Exists(KEY_NAME))
{
cngKey = CngKey.Create(CngAlgorithm.Rsa, KEY_NAME, cng);
}
else
{
cngKey = CngKey.Open(KEY_NAME);
}
RSACng rsaKey = new RSACng(cngKey)
{
KeySize = 2048
};
byte[] rsaPrvKeyExport = rsaKey.Key.Export(CngKeyBlobFormat.GenericPrivateBlob);
byte[] rsaPubKeyExport = rsaKey.Key.Export(CngKeyBlobFormat.GenericPublicBlob);
CngKey cngPrv = CngKey.Import(rsaPrvKeyExport, CngKeyBlobFormat.GenericPrivateBlob);
CngKey cngPub = CngKey.Import(rsaPubKeyExport, CngKeyBlobFormat.GenericPublicBlob);
//var signed = Sign512(Constants.STRING_TO_ENCODE.ToByteArray(), rsaPrvKeyExport);
string exportPrivateKey = Convert.ToBase64String(rsaKey.ExportPkcs8PrivateKey());
string pemString = $"{Constants.RSA_KEY_HEADER}\n{exportPrivateKey}\n{Constants.RSA_KEY_FOOTER}";
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
var certificate = BuildSelfSignedServerCertificate(rsaKey);
var thumbprint = certificate.Thumbprint;
store.Certificates.Add(certificate);
store.Close();
}
I know not all lines in this code are needed, but I am in the learning process.
So what I do here is create a cngKey Open the store. Create a Certificate from my cngKey Add the certificate to the store Close the store.
I generate a certificate from a cngKey using this code
private X509Certificate2 BuildSelfSignedServerCertificate(RSA key)
{
X500DistinguishedName distinguishedName = new X500DistinguishedName($"CN={Constants.CERTIFICATE_NAME}");
var request = new CertificateRequest(distinguishedName, key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
request.CertificateExtensions.Add(
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));
request.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false));
//request.CertificateExtensions.Add(sanBuilder.Build());
var certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
certificate.FriendlyName = Constants.CERTIFICATE_NAME;
return new X509Certificate2(certificate.Export(X509ContentType.Pfx, "WeNeedASaf3rPassword"), "WeNeedASaf3rPassword", X509KeyStorageFlags.MachineKeySet);
}
This gives no error, but when I open the certificate store I can't find it
I also tried to retrive it programmaticaly
using this bit of code
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates;
but my certificate is not here.
What am I missing, I am sure I am doing something wrong, but being new to this, I have no idea what.
Online I could not find a complete example of what I tried to achieve here.
CodePudding user response:
As @dimitar.bogdanov pointed out in comments, you are not adding the certificate to the store:
store.Certificates.Add(certificate);
here you are adding the certificate only to disconnected collection. Any changes in this collection object will not reflect actual store state. Instead, you have to use X509Store.Add method to update actual store.