Note that I use SHA512 but SHA256 will work with the below examples:
"Invalid algorithm specified" Took me forever to figure out and I tried practically everything.
Step 1 - the certificate has to be SHA512 and use a CSP (Cryptographic Service Provider) that is SHA512 Capable. Here is a list of CSPs and their capabilities. If you look for SHA512 you'll find the "Microsoft Enhanced RSA and AES Cryptographic Provider". By default generating certificates don't use this (at least in Windows) so you have to specify it when you create the certificate.
If you create the certificate with openssl, you can use the option -CSP below to set the correct CSP that will make it work. If you have an existing pfx, you can convert it to a PEM file with openssl, and then back to a pfx to add the option.
Create private key and certificate - this step will ask you questions, state, region etc etc.
openssl req -x509 -nodes -sha512 -newkey rsa:2048 -keyout 512key.pem -out 512cert.pem -days 3650
Create PFX file to import into your certificate store using the Microsoft Enhanced RSA and AES Cryptographic Provider:
openssl pkcs12 –export –in 512cert.pem –inkey 512key.pem –CSP “Microsoft Enhanced RSA and AES Cryptographic Provider” –out 512pfx.pfx
Step 2 : Props to Gonzalo Gallotti for posting the link to the piece of code that helped me. I commented up my code to show what each step is doing. NOTE: this code won't work without a properly generated certificate as described in step 1
public void GetCertificate() {
// Get the Machine Cert Store
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
string alg = CryptoConfig.MapNameToOID("SHA512");
// Open the cert store
store.Open(OpenFlags.ReadWrite);
// Loop through each certificate within the store
foreach (X509Certificate2 myCert in store.Certificates)
{
// Get the certificate we are looking for
if (myCert.IssuerName.Name.Contains("CN=YourSite"))
{
// Check if the certificate has a private key
if (myCert.HasPrivateKey)
{
// Get your custom signature as a string
string mySignature = GetSignatureString();
// Convert signature to byte array
byte[] originalData = Encoding.UTF8.GetBytes(mySignature);
// Create RSA provider from private key
RSACryptoServiceProvider rsaProvider = (RSACryptoServiceProvider)myCert.PrivateKey;
// Sign the signature with SHA512
byte[] signedSignature = signedSignature = rsaProvider.SignData(originalData, alg);
if (rsaProvider.VerifyData(originalData, alg, signedSignature))
{
// Signature is verified Do Stuff
}
else
{
throw new Exception("The data does not match the signature.");
}
}
}
}
}