azure - 将 DotNetOpenAuth OAuth 2 与 Azure 结合使用 - 读取证书 - 提取 key 时遇到困难

标签 azure dotnetopenauth oauth-2.0

DotNetOpenAuth OAuth 2 库需要 RSAParameters 来访问公钥和私钥(DotNetOpenAuth OAuth 2 - UriStyleMessageFormatter 中的示例,它使用 RSAParameters 构建 RSACryptoServiceProvider)。

我遇到了一个Azure Security Whitepaper其中指出,Azure 在“证书存储中安装证书,并带有一个标志,表明私钥可以使用但不能导出”。我认为这可能是这个问题的核心。

虽然我能够在本地开发和调试时通过指纹引用证书(下面的示例)从证书中提取公钥和私钥,但我没有运气在 Azure 中运行相同的代码。

以下代码给出错误:Azure 中的“ key 不适用于指定状态”

    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;
            }
        }

Azure 中的加密/解密代码基于同一证书(如下所示),无需导出 key 即可正常工作:

    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);
    }

除了重写 OAuth 2 库以使用 RSACryptoServiceProvider 引用而不是 RSAParameters 之外,还有什么方法可以让它在 Azure 中工作?

从商店读取证书时,是否有其他人遇到与 DotNetOpenAuth OAuth 2 和 Azure 相同的问题?

我希望避免黑客攻击,例如使用启动任务安装具有导出权限的证书(出于安全考虑)。

最佳答案

很好的反馈。我已经为此提交了一张罚单。 Please check

关于azure - 将 DotNetOpenAuth OAuth 2 与 Azure 结合使用 - 读取证书 - 提取 key 时遇到困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5064554/

相关文章:

c# - azure 中的 HiQPdf.HtmlToImage HTML 布局错误

python - 使用 Python 在 Twitter 1.1 中发出仅应用程序请求

azure - OIDC 允许用户用凭证交换 token

azure - 将对 Azure VM 的访问锁定到特定 IP

azure - 移动设备上的 Windows Azure Active Directory 身份验证速度缓慢

c# - 使用 Asp.net 4.0 实现 OAuth2

asp.net-mvc - 什么最适合认证 ASP.NET MVC REST API? OAuth 2.0 还是 OAuth 1.0?

c# - .net 中的 OpenID Connect 依赖方

oauth-2.0 - 使用 Identity Core 颁发不记名 JWT token

linux - 我的网站的子 URL 未在 Linux、Azure 和 Nginx 上加载 - 404 未找到