public void ItShouldBeDecodedCorrectly()
        {
            // encryptedData = FacebookUtils.Base64UrlDecode("YGym4poQnMTrEgiAOkFTVI85ll5RuUiEl-IgqfxTOTHQNIvVVI8Y8kVuOoeKaWOeassWFTEv0Qg_7wCCBEen7lUBBzlFJ1V63HJ3Af0SIngcxWTJ7L6YLatMmwXgDAvWn5PsfqzWk4ml9h9DLnYptWHmDGL6iBiOhN7WyI7p6oEpVriFuJw_chLoPb8a3vGDnoW8e2Sxx06A2x2xkiapvg");
            var encryptedData = new byte[]
            {
                96, 108, 166, 226, 154, 16, 156, 196, 235, 18, 8, 128, 58, 65, 83, 84, 143, 57, 150,
                94, 81, 185, 72, 132, 151, 226, 32, 169, 252, 83, 57, 49, 208, 52, 139, 213, 84, 143,
                24, 242, 69, 110, 58, 135, 138, 105, 99, 158, 106, 203, 22, 21, 49, 47, 209, 8, 63,
                239, 0, 130, 4, 71, 167, 238, 85, 1, 7, 57, 69, 39, 85, 122, 220, 114, 119, 1,
                253, 18, 34, 120, 28, 197, 100, 201, 236, 190, 152, 45, 171, 76, 155, 5, 224, 12,
                11, 214, 159, 147, 236, 126, 172, 214, 147, 137, 165, 246, 31, 67, 46, 118, 41, 181,
                97, 230, 12, 98, 250, 136, 24, 142, 132, 222, 214, 200, 142, 233, 234, 129, 41,
                86, 184, 133, 184, 156, 63, 114, 18, 232, 61, 191, 26, 222, 241, 131, 158, 133, 188,
                123, 100, 177, 199, 78, 128, 219, 29, 177, 146, 38, 169, 190
            };

            // key = Encoding.UTF8.GetBytes("13750c9911fec5865d01f3bd00bdf4db")
            var key = new byte[]
            {
                49, 51, 55, 53, 48, 99, 57, 57, 49, 49, 102, 101, 99, 53, 56, 54, 53, 100, 48, 49, 102, 51,
                98, 100, 48, 48, 98, 100, 102, 52, 100, 98
            };

            // iv = FacebookUtils.Base64UrlDecode("fDLJCW-yiXmuNa24eSarJg")
            var iv = new byte[] { 124, 50, 201, 9, 111, 178, 137, 121, 174, 53, 173, 184, 121, 38, 171, 38 };

            var result = FacebookWebUtils.DecryptAes256CBCNoPadding(encryptedData, key, iv);

            Assert.Equal(result, "{\"access_token\":\"101244219942650|2.wdrSr7KyE_VwQ0fjwOfW9A__.3600.1287608400-499091902|XzxMQd-_4tjlC2VEgide4rmg6LI\",\"expires_in\":6412,\"user_id\":\"499091902\"}");
        }
示例#2
0
        public void ItShouldBeDecodedCorrectly()
        {
            var encryptedData = FacebookWebUtils.Base64UrlDecode("YGym4poQnMTrEgiAOkFTVI85ll5RuUiEl-IgqfxTOTHQNIvVVI8Y8kVuOoeKaWOeassWFTEv0Qg_7wCCBEen7lUBBzlFJ1V63HJ3Af0SIngcxWTJ7L6YLatMmwXgDAvWn5PsfqzWk4ml9h9DLnYptWHmDGL6iBiOhN7WyI7p6oEpVriFuJw_chLoPb8a3vGDnoW8e2Sxx06A2x2xkiapvg");
            var key           = System.Text.Encoding.UTF8.GetBytes("13750c9911fec5865d01f3bd00bdf4db");
            var iv            = FacebookWebUtils.Base64UrlDecode("fDLJCW-yiXmuNa24eSarJg");

            var result = FacebookWebUtils.DecryptAes256CBCNoPadding(encryptedData, key, iv);

            Assert.Equal(result, "{\"access_token\":\"101244219942650|2.wdrSr7KyE_VwQ0fjwOfW9A__.3600.1287608400-499091902|XzxMQd-_4tjlC2VEgide4rmg6LI\",\"expires_in\":6412,\"user_id\":\"499091902\"}");
        }
示例#3
0
        /// <summary>
        /// Parse the signed request string.
        /// </summary>
        /// <param name="secret">
        /// The secret.
        /// </param>
        /// <param name="signedRequestValue">
        /// The signed request value.
        /// </param>
        /// <param name="maxAge">
        /// The max age.
        /// </param>
        /// <param name="currentTime">
        /// The current time.
        /// </param>
        /// <param name="throws">
        /// The throws.
        /// </param>
        /// <returns>
        /// The FacebookSignedRequest.
        /// </returns>
        internal static IDictionary <string, object> TryParse(string secret, string signedRequestValue, int maxAge, double currentTime, bool throws)
        {
            if (string.IsNullOrEmpty(secret))
            {
                throw new ArgumentNullException("secret");
            }
            if (string.IsNullOrEmpty(signedRequestValue))
            {
                throw new ArgumentNullException("signedRequestValue");
            }
            if (maxAge < 0)
            {
                throw new ArgumentOutOfRangeException("maxAge", "maxAge must be greater than 0");
            }
            if (currentTime < 0)
            {
                throw new ArgumentOutOfRangeException("currentTime", "currentTime must be greater than 0");
            }

            try
            {
                // NOTE: currentTime added to parameters to make it unit testable.
                string[] split = signedRequestValue.Split('.');
                if (split.Length != 2)
                {
                    // need to have exactly 2 parts
                    throw new InvalidOperationException(FacebookUtils.Resources.InvalidSignedRequest);
                }

                string encodedSignature = split[0];
                string encodedEnvelope  = split[1];

                if (string.IsNullOrEmpty(encodedSignature))
                {
                    throw new InvalidOperationException(FacebookUtils.Resources.InvalidSignedRequest);
                }

                if (string.IsNullOrEmpty(encodedEnvelope))
                {
                    throw new InvalidOperationException(FacebookUtils.Resources.InvalidSignedRequest);
                }

                var envelope = (IDictionary <string, object>)JsonSerializer.Current.DeserializeObject(Encoding.UTF8.GetString(FacebookWebUtils.Base64UrlDecode(encodedEnvelope)));

                string algorithm = (string)envelope["algorithm"];

                if (!algorithm.Equals("AES-256-CBC HMAC-SHA256") && !algorithm.Equals("HMAC-SHA256"))
                {
                    // TODO: test
                    throw new InvalidOperationException("Invalid signed request. (Unsupported algorithm)");
                }

                byte[] key    = Encoding.UTF8.GetBytes(secret);
                byte[] digest = FacebookWebUtils.ComputeHmacSha256Hash(Encoding.UTF8.GetBytes(encodedEnvelope), key);

                if (!digest.SequenceEqual(FacebookWebUtils.Base64UrlDecode(encodedSignature)))
                {
                    throw new InvalidOperationException(Facebook.Web.Properties.Resources.InvalidSignedRequestSignature);
                }

                IDictionary <string, object> result;

                if (algorithm.Equals("HMAC-SHA256"))
                {
                    // for requests that are signed, but not encrypted, we're done
                    result = envelope;
                }
                else
                {
                    result = new JsonObject();

                    result["algorithm"] = algorithm;

                    long issuedAt = (long)envelope["issued_at"];

                    if (issuedAt < currentTime)
                    {
                        throw new InvalidOperationException(Web.Properties.Resources.OldSignedRequest);
                    }

                    result["issued_at"] = issuedAt;

                    // otherwise, decrypt the payload
                    byte[] iv            = FacebookWebUtils.Base64UrlDecode((string)envelope["iv"]);
                    byte[] rawCipherText = FacebookWebUtils.Base64UrlDecode((string)envelope["payload"]);
                    var    plainText     = FacebookWebUtils.DecryptAes256CBCNoPadding(rawCipherText, key, iv);

                    var payload = (IDictionary <string, object>)JsonSerializer.Current.DeserializeObject(plainText);
                    result["payload"] = payload;
                }

                return(result);
            }
            catch
            {
                if (throws)
                {
                    throw;
                }

                return(null);
            }
        }