public static bool IsSignatureValid(IEnumerable <KeyValuePair <string, StringValues> > querystring, string securitySecret = null)
        {
            Action <IDictionary <string, string>, StringBuilder> buildStringFromParams = (param, strings) =>
            {
                foreach (var kvp in param)
                {
                    strings.AppendFormat("{0}={1}&", WebUtility.UrlEncode(kvp.Key), WebUtility.UrlEncode(kvp.Value));
                }
            };

            // Compare the local time with the timestamp
            var querystringList = querystring as IList <KeyValuePair <string, StringValues> > ?? querystring.ToList();
            var localTime       = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
            var messageTime     = int.Parse(querystringList.Single(kvp => kvp.Key == "timestamp").Value);
            // Message cannot be more than 5 minutes old
            const int maxDelta   = 5 * 60;
            var       difference = Math.Abs(localTime - messageTime);

            if (difference > maxDelta)
            {
                return(false);
            }

            var sorted = new SortedDictionary <string, string>();

            // Sort the query parameters, removing sig as we go
            foreach (var kvp in querystringList.Where(kv => kv.Key != "sig"))
            {
                sorted.Add(kvp.Key, kvp.Value);
            }
            // Create the signing url using the sorted parameters and your SECURITY_SECRET
            var sb = new StringBuilder();

            buildStringFromParams(sorted, sb);
            var queryToSign = "&" + sb;

            queryToSign = queryToSign.Remove(queryToSign.Length - 1) + (securitySecret?.ToUpper() ?? Configuration.Instance.Settings["appSettings:Nexmo.security_secret"].ToUpper());
            // Generate MD5
            var hashgen      = MD5.Create();
            var hash         = hashgen.ComputeHash(Encoding.UTF8.GetBytes(queryToSign));
            var generatedSig = ByteArrayToHexHelper.ByteArrayToHex(hash).ToLower();

            // A timing attack safe string comparison to validate hash
            return(SlowEquals(Encoding.UTF8.GetBytes(generatedSig),
                              Encoding.UTF8.GetBytes(querystringList.Single(kvp => kvp.Key == "sig").Value)));
        }
コード例 #2
0
        private static StringBuilder BuildQueryString(IDictionary <string, string> parameters, Credentials creds = null)
        {
            var apiKey         = (creds?.ApiKey ?? Configuration.Instance.Settings["appSettings:Nexmo.api_key"]).ToUpper();
            var apiSecret      = creds?.ApiSecret ?? Configuration.Instance.Settings["appSettings:Nexmo.api_secret"];
            var securitySecret = creds?.SecuritySecret ?? Configuration.Instance.Settings["appSettings:Nexmo.security_secret"];

            var sb = new StringBuilder();
            Action <IDictionary <string, string>, StringBuilder> buildStringFromParams = (param, strings) =>
            {
                foreach (var kvp in param)
                {
                    strings.AppendFormat("{0}={1}&", WebUtility.UrlEncode(kvp.Key), WebUtility.UrlEncode(kvp.Value));
                }
            };

            parameters.Add("api_key", apiKey);
            if (string.IsNullOrEmpty(securitySecret))
            {
                // security secret not provided, do not sign
                parameters.Add("api_secret", apiSecret);
                buildStringFromParams(parameters, sb);
                return(sb);
            }
            // security secret provided, sort and sign request
            parameters.Add("timestamp", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString(CultureInfo.InvariantCulture));
            var sortedParams = new SortedDictionary <string, string>(parameters);

            buildStringFromParams(sortedParams, sb);
            var queryToSign = "&" + sb;

            queryToSign = queryToSign.Remove(queryToSign.Length - 1) + securitySecret.ToUpper();
            var hashgen = MD5.Create();
            var hash    = hashgen.ComputeHash(Encoding.UTF8.GetBytes(queryToSign));

            sb.AppendFormat("sig={0}", ByteArrayToHexHelper.ByteArrayToHex(hash).ToLower());
            return(sb);
        }