• 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);
        }
  • 相关阅读:
    leetcode 33. Search in Rotated Sorted Array
    leetcode 32. Longest Valid Parentheses
    leetcode 28. Implement strStr()
    leetcode 27. Remove Element
    leetcode 26. Remove Duplicates from Sorted Array
    leetcode 24. Swap Nodes in Pairs
    leetcode 22. Generate Parentheses
    树莓派的频率管理和热控制
    sql执行insert插入一条记录同时获取刚插入的id
    全程直播个人博客重构过程,采用springboot+dubbo+jpa技术栈。
  • 原文地址:https://www.cnblogs.com/zhangliang2008/p/12706518.html
Copyright © 2020-2023  润新知