Using DotNetOpenAuth OAuth 2 with Azure Certificate - Read - Troubleshoot

The DotNetOpenAuth OAuth 2 library requires RSAParameters to access public and private keys (for example, in DotNetOpenAuth OAuth 2 - UriStyleMessageFormatter, which uses RSAP parameters to create RSACryptoServiceProvider).

I came across an Azure Security Whitepaper that noted that Azure installs certificates in a "certificate store with a flag indicating that the private key can be used but not exported." I believe this is at the heart of this problem.

While I was able to extract public and private keys from the certificate during development and debugging locally, referring to the certificate from this fingerprint (example below), I was not lucky that the same code works in Azure.

The following code gives an error: "The key is not valid for use in the specified state" in Azure

public class Global : System.Web.HttpApplication, IContainerAccessor { private static string thumbPrint = "<<my certificate thumbprint>>"; public static readonly RSAParameters AuthorizationServerSigningPublicKey = OAuthUtil.GetPublicKey(thumbPrint); internal static readonly RSAParameters ResourceServerEncryptionPrivateKey = OAuthUtil.GetPrivateKey(thumbPrint); //....... unnecessary code omitted ..... // public static class OAuthUtil { public static RSAParameters GetPublicKey(string thumbPrint) { X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly); var cert = store.Certificates.Find(X509FindType.FindByThumbprint, thumbPrint, true)[0]; var rsaParams = ((RSACryptoServiceProvider) cert.PublicKey.Key).ExportParameters(false); return rsaParams; } public static RSAParameters GetPrivateKey(string thumbPrint) { X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly); var cert = store.Certificates.Find(X509FindType.FindByThumbprint, thumbPrint, true)[0]; var rsaParams = ((RSACryptoServiceProvider) cert.PrivateKey).ExportParameters(true); return rsaParams; } } 

The Azure encryption / decryption code based on the same certificate (example below), which does not require key export, works fine:

  public class Certificate { public string FriendlyName { get; set; } public string IssuedBy { get; set; } public string IssuedTo { get; set; } public string ExpirationDate { get; set; } public string PublicKey { get; set; } public string PrivateKey { get; set; } } public ActionResult Keys() { X509Certificate2Collection selectedCerts = new X509Certificate2Collection(); var certList = new List<Certificate>(); X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); try { store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite); foreach (X509Certificate2 cert in store.Certificates) { // Encrypt string "hello world" CspParameters CSPParam = new CspParameters(); CSPParam.Flags = CspProviderFlags.UseMachineKeyStore; string PlainString = "hello world"; byte[] cipherbytes = ASCIIEncoding.ASCII.GetBytes(PlainString); RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PublicKey.Key; byte[] cipher = rsa.Encrypt(cipherbytes, false); var encryptedString = Convert.ToBase64String(cipher); var cert2 = cert; string decryptedString = "verify = " + cert2.Verify() ; if (cert2.HasPrivateKey && cert2.Verify()) { // Decrypt encrypted string.. RSACryptoServiceProvider rsaDecrypt = (RSACryptoServiceProvider)cert2.PrivateKey; byte[] cipherbytes2 = Convert.FromBase64String(encryptedString); byte[] plainbytes = rsaDecrypt.Decrypt(cipherbytes2, false); System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); decryptedString = enc.GetString(plainbytes); } var certItem = new Certificate { FriendlyName = cert.FriendlyName, IssuedBy = cert.Issuer, IssuedTo = cert.SubjectName.Name, ExpirationDate = cert.NotAfter.ToString("d"), PublicKey = "Public Key: " + cert.GetPublicKeyString() + "<br/>Encrypted String: " + encryptedString + "<br/>Decrypted String: " + decryptedString, PrivateKey = "cert has private key?: " + cert.HasPrivateKey + "<br/> key algo:" + cert.GetKeyAlgorithm() }; certList.Add(certItem); } } finally { store.Close(); } return View(certList); } 

Besides rewriting the OAuth 2 library to use RSACryptoServiceProvider links instead of RSAParameters, is there any way to make this work in Azure?

Does anyone else experience the same issue with DotNetOpenAuth OAuth 2 and Azure while reading certificates from the store?

I would like to avoid hacks such as installing a certificate with export privileges by running a task (due to security issues).

+4
source share
1 answer

Great feedback. I handed him a ticket. Please check

+3
source

Source: https://habr.com/ru/post/1340595/


All Articles