zoukankan      html  css  js  c++  java
  • Sign in with Apple 后端验证(C#)

    流程请参考:https://www.cnblogs.com/ljcgood66/p/12537389.html

    公钥验证

    /// <summary>
        /// 验证公钥
        /// </summary>
        /// <param name="jwtToken"></param>
        /// <returns></returns>
    
        public static bool VerifyPublicKey(string jwtToken)
        {
            var parts = jwtToken.Split('.');
            var header = JsonConvert.DeserializeObject<JObject>(Encoding.UTF8.GetString(FromBase64(parts[0])));
    
            var payload = JsonConvert.DeserializeObject<JObject>(Encoding.UTF8.GetString(FromBase64(parts[1])));
    
            // 第三部分是验证码,用来验证数据"{header}.{payload}"
            var signagure = FromBase64(parts[2]);
            var signedOver = Encoding.UTF8.GetBytes(parts[0] + "." + parts[1]);
            var keysJson = new WebClient().DownloadString("https://appleid.apple.com/auth/keys");
            var keys = JsonConvert.DeserializeObject<JObject>(keysJson)["keys"] as JArray;
            var key = keys.OfType<JObject>().FirstOrDefault(x => (string)x["kid"] == (string)header["kid"]);
            // 这里只支持RS256签名。RS256就是使用RSA算法,用一个RSA公钥,来验证数据的SHA256摘要。
            var alg = (string)key["alg"]; if (alg != "RS256");
            var n = FromBase64((string)key["n"]);
            var e = FromBase64((string)key["e"]);
            using (var rsa = new RSACryptoServiceProvider())
            {
                // 导入RSA公钥
                rsa.ImportParameters(new RSAParameters() { Exponent = e, Modulus = n });
                // 验证数据的SHA256摘要
                var signatureVerified = rsa.VerifyData(signedOver, signagure, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return signatureVerified;
            }
        }
        public static byte[] FromBase64(string base64WithoutPadding)
        {
            var base64 = base64WithoutPadding.Length % 4 == 0
                ? base64WithoutPadding
                : base64WithoutPadding + new string('=', 4 - base64WithoutPadding.Length % 4);
    
            return Convert.FromBase64String(base64.Replace("-", "+").Replace('_', '/'));
        }

    创建client_secret 

     static void Main(string[] args)
        {
            var team_id = "xxxxx";
            var ecdsaPrivateKey = ReadPrivateKey();
            var now = DateTime.UtcNow;
            var signing = new SigningCredentials(new ECDsaSecurityKey(ecdsaPrivateKey), SecurityAlgorithms.EcdsaSha256);
            var header = new JwtHeader(signing);
            var jwtHandler = new JwtSecurityTokenHandler() { };
            var payload = new JwtPayload(team_id, "https://appleid.apple.com", new List<Claim> { new Claim("sub", "xxx.xx.xxx") }, now, now.AddSeconds(86400 * 30), now);
            header.Add("kid", "xxxx");
            header.Remove("typ");
            var jwtSecurity = new JwtSecurityToken(header, payload);
            var jwtToken = jwtHandler.WriteToken(jwtSecurity);
            ecdsaPrivateKey.Dispose();
            Console.WriteLine(jwtToken);
    
        }
    
        static ECDsa ReadPrivateKey()
        {
    
            // 可以用BouncyCastle的ArmoredInputStream来脱壳,处理比较周全。
            var p8 =File.ReadAllText("p8文件");
    
            // 这里直接用去头去尾的方法:
            var lines = p8.Split('
    ');
            var trimmed = string.Join("", lines.Skip(1).Take(lines.Length - 2).Select(l => l.Trim()));
            var keyBlob = Convert.FromBase64String(trimmed);
    
            // CngKey是微软的实现。如果你的密钥无法读出,试试用BouncyCastle来处理
            var privateKey = CngKey.Import(keyBlob, CngKeyBlobFormat.Pkcs8PrivateBlob);
            return new ECDsaCng(privateKey);
        }
  • 相关阅读:
    2019.8.6原型链与继承
    2019.8.2闭包,作用域
    2019.8.1正则二
    2019.7.31正则
    2019.7.29二维数组
    2019.7.28关于数组和循环的八道题
    2019.7.27数组api
    DOM
    JavaScript数组5种去重方法
    JavaScript面向对象
  • 原文地址:https://www.cnblogs.com/zhangliang2008/p/12706518.html
Copyright © 2011-2022 走看看