One of my certificates have been expired. This makes the following code fail :
X509Store store = new X509Store(settings.CertificateStore, settings.CertificateLocation);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, settings.Thumbprint, true);
store.Close();
if (certs.Count > 0)
{
LogHandler.Instance.Log(LogLev.Info, $"UseSecureConnection > Location:{settings.CertificateLocation}, Store:{settings.CertificateStore}, Thumbprint:{settings.Thumbprint}");
_serviceHost.Credentials.ServiceCertificate.SetCertificate(settings.CertificateLocation,
settings.CertificateStore, X509FindType.FindByThumbprint, settings.Thumbprint);
}
else
throw new Exception("Could not find certificate with thumbprint " + settings.Thumbprint);
This codes worked great uptil certificate got expired.
How do i fetch it even if its expired?
store.Certificates.Find(X509FindType.FindByThumbprint, settings.Thumbprint, false)
should do it. The last parameter is validOnly.
Related
I am using the below method to get certificate from the x509 store
private X509Certificate GetCert(string certThumbPrint)
{
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbPrint.Trim(), false);
certStore.Close();
// Check to see if our certificate was added to the collection. If no, throw an error, if yes, create a certificate using it.
if (0 == certCollection.Count || certCollection.Count == null)
{
throw new ApiException(string.Format("Error: Admin Service Client : No certificate found containing thumbprint {0}",certThumbPrint), ApiLogCategory.Configuration, ErrorCodes.AdminServiceClient);
}
var cert = new X509Certificate(certCollection[0].RawData, string.Empty, X509KeyStorageFlags.MachineKeySet);
return cert;
}
I was getting error so I tried debugging and found that the application is unable to open the X509 store. What can I do in this case.
It looks like a permission related issue.
Is your certificate installed in personal store?
if so, Right click the certificate => All tasks => Manage private key => Add IIS AppPool\AppPoolName and grant it Full control
if you're running app pool under a different account than application pool identity then that that user.
I need to access a certificate from my Azure Function.
I followed the steps outlined in Runtime error loading certificate in Azure Functions but it didn't work out.
private static X509Certificate2 GetCertificate(string thumbprint, TraceWriter log)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly);
log.Info("Enumerating certificates");
foreach (var cert in store.Certificates) {
log.Info(cert.Subject);
}
var col = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (col == null || col.Count == 0)
{
return null;
}
return col[0];
}
finally
{
store.Close();
}
}
Two certificates where uploaded to the Azure Function and the setting WEBSITE_LOAD_CERTIFICATES was added as well and set to either * or to the thumpbrint of the required certificate, but to no avail.
The GetCertificate method should print a list of all certificates in the store, but the store is empty.
Any clues on how to solve this?
UPDATE:
Client certificates are now supported in the Consumption plan.
Client certificates are not yet supported in our Consumption plan, only in App Service plan. This is tracked by an issue in our repo here. We're working on it - please follow that issue for status. Thanks.
I want to switch from self-signed certificate per device to pair of certificates, one of which is previously generated, placed in Trusted Root Certificate Authorities store, is same for all devices, and works as root CA for second certificate, which is generated per device, and placed in Personal store.
I would like to not use makecert, since creating signed certificate shows up UI, which I want to avoid. Also, OpenSSL can't be used due to some license-related stuff (although I have working solution with it). So, for now I'm working with small C# tool, based on CertEnroll lib.
This is how I create pfx for first, root CA certificate.
makecert -n "CN=Root CA" -cy authority -r -a sha256 -len 2048 -sv root.pvk root.cer
pvk2pfx -pvk root.pvk -spc root.cer -pfx root.pfx -pi 123 -po 123
To create certificate from C# code, I've referenced questions How to create self-signed certificate programmatically for WCF service? and C# Generate a non self signed client CX509Certificate Request without a CA using the certenroll.dll.
So far, I have following code. Method for certificate generation:
/// <summary>
/// Generates self-signed certificate with specified subject, which will expire after specified timespan.
/// </summary>
public X509Certificate2 CreateCertificate(string subjectName, TimeSpan expirationLength, X509Certificate2 issuer = null)
{
// create DN for subject and issuer
var dn = new CX500DistinguishedName();
dn.Encode("CN=" + subjectName);
var issuerName = new CX500DistinguishedName();
if(issuer != null)
{
issuerName.Encode(issuer.Subject);
}
var privateKey = new CX509PrivateKey
{
ProviderName = "Microsoft Strong Cryptographic Provider",
Length = 2048,
KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE,
KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_DECRYPT_FLAG |
X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG,
MachineContext = true,
ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG
};
privateKey.Create();
// Use the stronger SHA512 hashing algorithm
var hashobj = new CObjectId();
hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY,
AlgorithmFlags.AlgorithmFlagsNone, "SHA512");
var cert = new CX509CertificateRequestCertificate();
cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, "");
cert.Subject = dn;
if (issuer != null)
cert.Issuer = issuerName;
else
cert.Issuer = dn;
cert.NotBefore = DateTime.Now.Date;
cert.NotAfter = cert.NotBefore + expirationLength;
cert.HashAlgorithm = hashobj; // Specify the hashing algorithm
if(issuer != null)
{
var signerCertificate = new CSignerCertificate();
signerCertificate.Initialize(true, X509PrivateKeyVerify.VerifyAllowUI, EncodingType.XCN_CRYPT_STRING_HEX, issuer.GetRawCertDataString());
cert.SignerCertificate = signerCertificate;
}
cert.Encode();
// Do the final enrollment process
var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(cert); // load the certificate
enroll.CertificateFriendlyName = subjectName; // Optional: add a friendly name
var csr = enroll.CreateRequest(); // Output the request in base64
// and install it back as the response
enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
csr, EncodingType.XCN_CRYPT_STRING_BASE64, ""); // no password
// output a base64 encoded PKCS#12 so we can import it back to the .Net security classes
var base64encoded = enroll.CreatePFX("", // no password, this is for internal consumption
PFXExportOptions.PFXExportChainWithRoot);
// instantiate the target class with the PKCS#12 data (and the empty password)
return new X509Certificate2(Convert.FromBase64String(base64encoded), "",
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
}
Simple application to find existing certificate and create new one based on it:
static void Main(string[] args)
{
var certificateGenerator = new CertificateGenerator();
X509Certificate2 rootCA;
using (var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadWrite);
rootCA = store.Certificates.OfType<X509Certificate2>()
.FirstOrDefault(c => c.Subject.StartsWith("CN=Root CA", StringComparison.Ordinal));
store.Close();
}
if (rootCA == null)
throw new Exception("Can't find root CA certificate");
var testCert = certificateGenerator.CreateCertificate("Test", new TimeSpan(3650, 0, 0, 0), rootCA);
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadWrite);
store.Add(testCert);
store.Close();
}
}
The thing is, that it works great, if I try to reference certificate not in Trusted Root Certificate Authorities, but in Personal (even if I have password on certificate). But if I try to create certificate based on CA certificate from Trusted Root Certificate Authorities, I receive exception on signerCertificate.Initialize, saying
Cannot find object or property. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)
So, what am I missing?
ISignerCertificate::Initialize requires that the private key be bound via the Requests or My store:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa376832(v=vs.85).aspx:
If a private key is needed, only the personal and request stores are
searched.
If a private key is not needed, the root and intermediate CA
stores are also searched.
Windows expects that you only put the public portion of the CA into the CA (intermediate) or Root/ThirdPartyRoot stores, and that if you're the issuer you'll ALSO have it installed (with the private key now) into CurrentUser\My or LocalMachine\My.
I have uploaded Certificates thorough azure new portal while i am not getting these certificates back here is my code
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates;
try
{
}
finally
{
store.Close();
}
return certificates;
These are the certificates which I always get
enter image description here
Also i have follow this article https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/
Anybody know the reason why i am not getting all the certificates and why i am getting these certificates ?? please help
instead of geeting all certificates i just received these 4, and in the local enviorment i get all certificates which are install on my machine
From my test, the article in your reply help us to use Certificates in Azure web app. However we only could query the certificates with the following conditions:
1) the certificate has been uploaded to Azure web app
2) setting WEBSITE_LOAD_CERTIFICATES in Azure portal with its value set to the certificate thumbprint
It is different with your test on your local machine because Azure web app run in sandbox. For more information about Azure web app sandbox, please refer to this article.
Well, I'm using this function I had found somewhere and is working fine. If you have uploaded all the certificates properly, can you please try running this piece of code. I know it looks the same but you can't really tell.
private X509Certificate2 GetStoreCertificate(string thumbprint)
{
List<StoreLocation> locations = new List<StoreLocation> { StoreLocation.CurrentUser, StoreLocation.LocalMachine };
foreach (var location in locations)
{
Console.WriteLine("location: " + location.ToString());
X509Store store = new X509Store("My", location);
try
{
Console.WriteLine("Try, store.Open...");
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
Console.WriteLine("store.Opened..." + store.Certificates.Count.ToString());
foreach (X509Certificate2 cert in store.Certificates)
{
Console.WriteLine("X509Certificate2 Thumbprint : " + cert.Thumbprint);
}
foreach (X509Certificate cert in store.Certificates)
{
Console.WriteLine("X509Certificate Thumbprint : " + cert.Issuer);
}
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
Console.WriteLine("Finding certificate.." + certificates.Count.ToString());
if (certificates.Count == 1)
{
Console.WriteLine("Atleast one found!!!");
return certificates[0];
}
}
finally
{
store.Close();
}
}
throw new ArgumentException(string.Format("A Certificate with Thumbprint '{0}' could not be located.", thumbprint));
}
I try to load a x509 certificate to use in a WCF client. for this i use the SetDefaultCertificate function but this function throw a exception.
var clientWS = new WS_eFacturaSoapPortClient();
clientWS.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
StoreLocation.CurrentUser, StoreName.My,
X509FindType.FindBySubjectKeyIdentifier, "79852b4fab95e8cd1f6e36167bbb895bd4cbe767");
The exception:
Cannot find the X.509 certificate using the following search criteria:
StoreName 'My', StoreLocation 'CurrentUser', FindType
'FindBySubjectKeyIdentifier', FindValue
'79852b4fab95e8cd1f6e36167bbb895bd4cbe767'.
But if I do this...
X509Certificate2 cert = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection col = store.Certificates.Find(
X509FindType.FindBySubjectKeyIdentifier, "79852b4fab95e8cd1f6e36167bbb895bd4cbe767", true);
cert = col[0];
}
// Cerrar el store
finally { store.Close(); }
The certificate is founded.
What i do wrong?, is posible add the x509Certificate2 to the ClientCredentials?
I changed the FindType to FindBySerialNumber and it works.
clientWS.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
StoreLocation.CurrentUser, StoreName.My,
X509FindType.FindBySerialNumber, "0cf43655217b8853e2df0b931d2c352afa93d9");
this post helped me.