api接口签名验证

方式一:AuthorizeFilter

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyTest.Common
{
    public class SignAuthorzation : AuthorizeFilter
    {
        string signaturekey = "fba503abf3a411e9b97f00163e129d15"; //签名密钥
        int timeOut = 120; //签名超时时间(单位:秒)


        public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            try
            {
                var httpContext = context.HttpContext;
                if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value != "/favicon.ico")
                {                             
                    var sign = string.Empty; //签名
                    var timestamp = string.Empty;//时间戳
                    var query = new Dictionary<string, object>();
                    if (httpContext.Request.Method == "GET")
                    {//get方式获取请求参数     
                        var queryParam = httpContext.Request.Query.Keys.ToArray();
                        foreach (var item in queryParam)
                        {
                            var val = httpContext.Request.Query[item].ToString();
                            if (item == "sign")
                            {
                                sign = val;
                                continue;
                            }
                            if (item == "timestamp")
                            {
                                timestamp = httpContext.Request.Query[item].ToString();
                            }
                            query.Add(item, val);
                        }
                    }
                    else
                    {//post方式获取请求参数
                        using (Stream stream = httpContext.Request.Body)
                        {
                            byte[] buffer = new byte[httpContext.Request.ContentLength.Value];
                            stream.Read(buffer, 0, buffer.Length);
                            httpContext.Request.Body = new System.IO.MemoryStream(buffer);  
                            string postData = Encoding.UTF8.GetString(buffer);                       
                            query = JsonConvert.DeserializeObject<Dictionary<string, object>>(postData);
                            var postParam = string.Empty;
                            foreach (var item in query.ToList())
                            {                               
                                if (item.Key == "sign")
                                {
                                    sign = item.Value.ToString();
                                    query.Remove(item.Key);
                                }
                                if (item.Key == "timestamp")
                                {
                                    timestamp = item.Value.ToString();
                                }                              
                            }
                        }
                    }

                    if (string.IsNullOrWhiteSpace(sign))
                    {
                        context.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数sign" });
                        return;
                    }
                    if (string.IsNullOrWhiteSpace(timestamp))
                    {
                        context.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数timestamp" });
                        return;
                    }
                    var requestTime = ConvertStringToDateTime(timestamp);
                    long time1 = DateTime.Now.Ticks;
                    long time2 = requestTime.Ticks;
                    long interval = (time1 - time2) / 10000000;
                    //判断签名时间
                    if (interval > timeOut)
                    {
                        context.Result = new JsonResult(new { Code = 0, Msg = "签名超时" });
                    }
                    else
                    {
                        //生成签名
                        var signStr = GetQueryString(query);
                        //MD5加密
                        var signReal = signStr.Md5().ToLower();
                        //判断签名
                        if (signReal != sign.ToLower())
                        {
                            context.Result = new JsonResult(new { Code = 0, Msg = "签名错误" });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                context.Result = new JsonResult(new { Code = 500, Msg = "签名验证异常" });
            }
        }

        /// <summary>
        /// 拼接参数
        /// 签名生成规则如下:参与签名的字段包括请求的参数,  timestamp(时间戳),签名密钥 signaturekey。
        /// 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后(signaturekey不参与排序,放在最后),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1
        /// </summary>
        /// <param name="parames"></param>
        /// <returns></returns>
        public string GetQueryString(Dictionary<string, object> parames)
        {
            var arr = parames.Keys.ToArray();
            Array.Sort(arr, string.CompareOrdinal);//按Ascll码排序  
            List<string> query = new List<string>();
            if (parames == null || parames.Count == 0)
            {
                return "";
            }
            foreach (var item in arr)
            {
                query.Add($"{item}={parames[item]}");
            }
            query.Add($"signaturekey={signaturekey}");
            return string.Join("&", query);
        }

        /// <summary>        
        /// 时间戳转换时间   
        /// </summary>        
        /// <param name=”timestamp”></param>        
        /// <returns></returns>        
        public DateTime ConvertStringToDateTime(string timestamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timestamp + "0000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }
    }
}

在Startup.cs的ConfigureServices方法中添加以下语句:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options => {             
                options.Filters.Add<SignAuthorzation>();
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);  
        }

方式二:ActionFilterAttribute

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace MyTest.Common
{
    public class SignAuthFilterAttribute : ActionFilterAttribute
    {
        string signaturekey = "fba503abf3a411e9b97f00163e129d15"; //签名密钥
        int timeOut = 120; //签名超时时间(单位:秒)
      
        public override void OnActionExecuting(ActionExecutingContext actionContext)
        {
            try
            {
                var httpContext = actionContext.HttpContext;
                if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value != "/favicon.ico")
                {                
                    var sign = string.Empty; //签名
                    var timestamp = string.Empty;//时间戳
                    var query = new Dictionary<string, object>();
                    if (httpContext.Request.Method == "GET")
                    {//get方式获取请求参数                                
                        var queryParam = httpContext.Request.Query.Keys.ToArray();
                        foreach (var item in queryParam)
                        {
                            var val = httpContext.Request.Query[item].ToString();                         
                            if (item == "sign")
                            {
                                sign = val;
                                continue;
                            }
                            if (item == "timestamp")
                            {
                                timestamp = httpContext.Request.Query[item].ToString();
                            }
                            query.Add(item, val);      
                        }
                    }
                    else
                    {//post方式获取请求参数
                        using (Stream stream = httpContext.Request.Body)
                        {
                            httpContext.Request.Body.Position = 0;  
                            byte[] buffer = new byte[httpContext.Request.ContentLength.Value];
                            stream.Read(buffer, 0, buffer.Length);
                            string postData = Encoding.UTF8.GetString(buffer);
                            query = JsonConvert.DeserializeObject<Dictionary<string, object>>(postData);                       
                            foreach (var item in query.ToList())
                            {                              
                                if (item.Key == "sign")
                                {
                                    sign = item.Value.ToString();
                                    query.Remove(item.Key);
                                }
                                if (item.Key == "timestamp")
                                {
                                    timestamp = item.Value.ToString();
                                }                               
                            }
                        }
                    }

                    if (string.IsNullOrWhiteSpace(sign))
                    {
                        actionContext.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数sign" });
                        return;
                    }
                    if (string.IsNullOrWhiteSpace(timestamp))
                    {
                        actionContext.Result = new JsonResult(new { Code = 0, Msg = "缺少签名参数timestamp" });
                        return;
                    }

                    var requestTime = ConvertStringToDateTime(timestamp);
                    long time1 = DateTime.Now.Ticks;
                    long time2 = requestTime.Ticks;
                    long interval = (time1 - time2) / 10000000;
                    //判断签名时间
                    if (interval > timeOut)
                    {
                        actionContext.Result = new JsonResult(new { Code = 0, Msg = "签名超时" });
                    }
                    else
                    {                 
                        //生成签名
                        var signStr = GetQueryString(query);                       
                        //MD5加密
                        var signReal = signStr.Md5().ToLower();
                        //判断签名
                        if (signReal != sign.ToLower())
                        {
                            actionContext.Result = new JsonResult(new { Code = 0, Msg = "签名错误" });
                        }
                    }
                }
               
            }
            catch (Exception ex)
            {
                actionContext.Result = new JsonResult(new { Code = 500, Msg = "签名验证异常" });
            }
        }

        /// <summary>
        /// 拼接参数
        /// 签名生成规则如下:参与签名的字段包括请求的参数,  timestamp(时间戳),签名密钥 signaturekey。
        /// 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后(signaturekey不参与排序,放在最后),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1
        /// </summary>
        /// <param name="parames"></param>
        /// <returns></returns>
        public string GetQueryString(Dictionary<string, object> parames)
        {
            var arr = parames.Keys.ToArray();
            Array.Sort(arr, string.CompareOrdinal);//按Ascll码排序  
            List<string> query = new List<string>();
            if (parames == null || parames.Count == 0)
            {
                return "";
            }               
            foreach (var item in arr)
            {
                query.Add($"{item}={parames[item]}");              
            }
            query.Add($"signaturekey={signaturekey}");
            return string.Join("&", query);
        }

        /// <summary>        
        /// 时间戳转换时间   
        /// </summary>        
        /// <param name=”timestamp”></param>        
        /// <returns></returns>        
        public DateTime ConvertStringToDateTime(string timestamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timestamp + "0000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }
    }
}

在Startup.cs的ConfigureServices方法中添加以下语句:

      public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options => {
                options.Filters.Add<SignAuthFilterAttribute>();                
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);           
        }

方式三:

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace MyTest.Common
{
    public class SignCheck
    {
        string signaturekey = "fba503abf3a411e9b97f00163e129d15"; //签名密钥
        int timeOut = 120; //签名超时时间(单位:秒)

        private readonly RequestDelegate _next;
        
        public SignCheck(RequestDelegate next)
        {
            _next = next;
        }
        
        public Task Invoke(HttpContext httpContext)
        {
            try
            {
                if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value != "/favicon.ico")
                {
                    var sign = string.Empty; //签名
                    var timestamp = string.Empty;//时间戳
                    var query = new Dictionary<string, object>();
                    if (httpContext.Request.Method == "GET")
                    {//get方式获取请求参数     
                        var queryParam = httpContext.Request.Query.Keys.ToArray();
                        foreach (var item in queryParam)
                        {
                            var val = httpContext.Request.Query[item].ToString();
                            if (item == "sign")
                            {
                                sign = val;
                                continue;
                            }
                            if (item == "timestamp")
                            {
                                timestamp = httpContext.Request.Query[item].ToString();
                            }
                            query.Add(item, val);
                        }
                    }
                    else
                    {
                        var memery = new System.IO.MemoryStream();
                        httpContext.Request.Body.CopyTo(memery);
                        memery.Position = 0;
                        var postData = new System.IO.StreamReader(memery, System.Text.UTF8Encoding.UTF8).ReadToEnd();                      
                        memery.Position = 0;
                        httpContext.Request.Body = memery;                
                        query = JsonConvert.DeserializeObject<Dictionary<string, object>>(postData);
                        var postParam = string.Empty;
                        foreach (var item in query.ToList())
                        {                         
                            if (item.Key == "sign")
                            {
                                sign = item.Value.ToString();
                                query.Remove(item.Key);
                            }
                            if (item.Key == "timestamp")
                            {
                                timestamp = item.Value.ToString();
                            }                          
                        }
                    }

                    if (string.IsNullOrWhiteSpace(sign))
                    {
                        httpContext.Response.StatusCode = 401;
                        return httpContext.Response.WriteAsync("缺少签名参数sign");
                    }
                    if (string.IsNullOrWhiteSpace(timestamp))
                    {
                        httpContext.Response.StatusCode = 401;
                        return httpContext.Response.WriteAsync("缺少签名参数timestamp");
                    }

                    var requestTime = ConvertStringToDateTime(timestamp);
                    long time1 = DateTime.Now.Ticks;
                    long time2 = requestTime.Ticks;
                    long interval = (time1 - time2) / 10000000;                  
                   
                    if (interval > timeOut)
                    {
                        httpContext.Response.StatusCode = 401;
                        return httpContext.Response.WriteAsync("Signature error");
                    }
                    else
                    {
                        //生成签名
                        var signStr = GetQueryString(query);
                        //MD5加密
                        var signReal = signStr.Md5().ToLower();
                        //判断签名
                        if (signReal != sign.ToLower())
                        {
                            httpContext.Response.StatusCode = 401;
                            return httpContext.Response.WriteAsync("Signature error");
                        }
                    }
                }
                return _next(httpContext);
            }
            catch (Exception ex)
            {
                
                return null;
            }
        }

        /// <summary>
        /// 拼接参数
        /// 签名生成规则如下:参与签名的字段包括请求的参数,  timestamp(时间戳),签名密钥 signaturekey。
        /// 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后(signaturekey不参与排序,放在最后),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1
        /// </summary>
        /// <param name="parames"></param>
        /// <returns></returns>
        public string GetQueryString(Dictionary<string, object> parames)
        {
            var arr = parames.Keys.ToArray();
            Array.Sort(arr, string.CompareOrdinal);//按Ascll码排序  
            List<string> query = new List<string>();
            if (parames == null || parames.Count == 0)
            {
                return "";
            }
            foreach (var item in arr)
            {
                query.Add($"{item}={parames[item]}");
            }
            query.Add($"signaturekey={signaturekey}");
            return string.Join("&", query);
        }

        /// <summary>        
        /// 时间戳转换时间   
        /// </summary>        
        /// <param name=”timestamp”></param>        
        /// <returns></returns>        
        public DateTime ConvertStringToDateTime(string timestamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timestamp + "0000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }
    }
}

在Startup.cs的Configure方法中添加以下语句:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }          
            app.UseMiddleware<SignCheck>(); 
            app.UseHttpsRedirection();
            app.UseMvc();
        }

  

Md5加密方式:

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace MyTest.Common
{
    public static class EncryptHelper
    {
        /// <summary>
        /// 基于Md5的自定义加密字符串方法:输入一个字符串,返回一个由32个字符组成的十六进制的哈希散列(字符串)。
        /// </summary>
        /// <param name="str">要加密的字符串</param>
        /// <returns>加密后的十六进制的哈希散列(字符串)</returns>
        public static string Md5(this string str)
        {           
            var buffer = Encoding.Default.GetBytes(str);           
            var data = MD5.Create().ComputeHash(buffer);            
            var sb = new StringBuilder();
            foreach (var t in data)
            {
                sb.Append(t.ToString("X2"));
            }
            return sb.ToString();
        }
   
    }
}

前端调用示例:

<script type="text/javascript" src="jquery-2.1.4.js"></script>
<script type="text/javascript" src="md5.js"></script>  

<input type="button" value="测试" onclick="GetUser()" />


<script type="text/javascript">

        function getNewObj(obj) {
            var timestamp = (new Date()).valueOf();//时间戳
            obj.timestamp = timestamp;
            var newKey = Object.keys(obj).sort();
            var queryArray = new Array();
            for (var i = 0; i < newKey.length; i++) {
                queryArray.push(newKey[i] + "=" + obj[newKey[i]]);
            }
            queryArray.push("signaturekey=fba503abf3a411e9b97f00163e129d15");
            var signStr = queryArray.join("&");
            var sign = md5(signStr);
            obj.sign = sign;         
            return obj;
        }

        function GetUser() {
            var item = {
                "PageIndex": 1,
                "PageSize": 10,
                "UserId": 1,
                "Status": -1
            }

            var newobj1 = getNewObj(item);
            $.ajax({
                url: "http://localhost:9002/User/GetUser",
                dataType: "json",
                async: true,
                data: newobj1,
                type: "GET",
                success: function (result) {
                    console.log(result)
                    alert(JSON.stringify(result));
                },
                error: function () {
                }
            });
        }
</script>

如果是前端直接调用需要设置api允许跨域:

在Startup.cs的ConfigureServices方法中增加:   

services.AddCors(option => option.AddPolicy("AllowCors", builder => builder.AllowAnyMethod().AllowAnyHeader().AllowCredentials().AllowAnyOrigin()));

在Startup.cs的Configure方法中增加:

  app.UseCors("AllowCors");

 md5.js 

/*
 * JavaScript MD5 1.0.1
 * https://github.com/blueimp/JavaScript-MD5
 *
 * Copyright 2011, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 * 
 * Based on
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*jslint bitwise: true */
/*global unescape, define */

(function ($) {
    'use strict';

    /*
    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
    * to work around bugs in some JS interpreters.
    */
    function safe_add(x, y) {
        var lsw = (x & 0xFFFF) + (y & 0xFFFF),
            msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        return (msw << 16) | (lsw & 0xFFFF);
    }

    /*
    * Bitwise rotate a 32-bit number to the left.
    */
    function bit_rol(num, cnt) {
        return (num << cnt) | (num >>> (32 - cnt));
    }

    /*
    * These functions implement the four basic operations the algorithm uses.
    */
    function md5_cmn(q, a, b, x, s, t) {
        return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
    }
    function md5_ff(a, b, c, d, x, s, t) {
        return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
    }
    function md5_gg(a, b, c, d, x, s, t) {
        return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
    }
    function md5_hh(a, b, c, d, x, s, t) {
        return md5_cmn(b ^ c ^ d, a, b, x, s, t);
    }
    function md5_ii(a, b, c, d, x, s, t) {
        return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
    }

    /*
    * Calculate the MD5 of an array of little-endian words, and a bit length.
    */
    function binl_md5(x, len) {
        /* append padding */
        x[len >> 5] |= 0x80 << (len % 32);
        x[(((len + 64) >>> 9) << 4) + 14] = len;

        var i, olda, oldb, oldc, oldd,
            a = 1732584193,
            b = -271733879,
            c = -1732584194,
            d = 271733878;

        for (i = 0; i < x.length; i += 16) {
            olda = a;
            oldb = b;
            oldc = c;
            oldd = d;

            a = md5_ff(a, b, c, d, x[i], 7, -680876936);
            d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
            c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
            b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
            a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
            d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
            c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
            b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
            a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
            d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
            c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
            b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
            a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
            d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
            c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
            b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);

            a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
            d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
            c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
            b = md5_gg(b, c, d, a, x[i], 20, -373897302);
            a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
            d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
            c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
            b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
            a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
            d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
            c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
            b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
            a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
            d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
            c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
            b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);

            a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
            d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
            c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
            b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
            a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
            d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
            c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
            b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
            a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
            d = md5_hh(d, a, b, c, x[i], 11, -358537222);
            c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
            b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
            a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
            d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
            c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
            b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);

            a = md5_ii(a, b, c, d, x[i], 6, -198630844);
            d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
            c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
            b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
            a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
            d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
            c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
            b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
            a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
            d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
            c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
            b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
            a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
            d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
            c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
            b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);

            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd);
        }
        return [a, b, c, d];
    }

    /*
    * Convert an array of little-endian words to a string
    */
    function binl2rstr(input) {
        var i,
            output = '';
        for (i = 0; i < input.length * 32; i += 8) {
            output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
        }
        return output;
    }

    /*
    * Convert a raw string to an array of little-endian words
    * Characters >255 have their high-byte silently ignored.
    */
    function rstr2binl(input) {
        var i,
            output = [];
        output[(input.length >> 2) - 1] = undefined;
        for (i = 0; i < output.length; i += 1) {
            output[i] = 0;
        }
        for (i = 0; i < input.length * 8; i += 8) {
            output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
        }
        return output;
    }

    /*
    * Calculate the MD5 of a raw string
    */
    function rstr_md5(s) {
        return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
    }

    /*
    * Calculate the HMAC-MD5, of a key and some data (raw strings)
    */
    function rstr_hmac_md5(key, data) {
        var i,
            bkey = rstr2binl(key),
            ipad = [],
            opad = [],
            hash;
        ipad[15] = opad[15] = undefined;
        if (bkey.length > 16) {
            bkey = binl_md5(bkey, key.length * 8);
        }
        for (i = 0; i < 16; i += 1) {
            ipad[i] = bkey[i] ^ 0x36363636;
            opad[i] = bkey[i] ^ 0x5C5C5C5C;
        }
        hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
        return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
    }

    /*
    * Convert a raw string to a hex string
    */
    function rstr2hex(input) {
        var hex_tab = '0123456789abcdef',
            output = '',
            x,
            i;
        for (i = 0; i < input.length; i += 1) {
            x = input.charCodeAt(i);
            output += hex_tab.charAt((x >>> 4) & 0x0F) +
                hex_tab.charAt(x & 0x0F);
        }
        return output;
    }

    /*
    * Encode a string as utf-8
    */
    function str2rstr_utf8(input) {
        return unescape(encodeURIComponent(input));
    }

    /*
    * Take string arguments and return either raw or hex encoded strings
    */
    function raw_md5(s) {
        return rstr_md5(str2rstr_utf8(s));
    }
    function hex_md5(s) {
        return rstr2hex(raw_md5(s));
    }
    function raw_hmac_md5(k, d) {
        return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
    }
    function hex_hmac_md5(k, d) {
        return rstr2hex(raw_hmac_md5(k, d));
    }

    function md5(string, key, raw) {
        if (!key) {
            if (!raw) {
                return hex_md5(string);
            }
            return raw_md5(string);
        }
        if (!raw) {
            return hex_hmac_md5(key, string);
        }
        return raw_hmac_md5(key, string);
    }

    if (typeof define === 'function' && define.amd) {
        define(function () {
            return md5;
        });
    } else {
        $.md5 = md5;
    }
}(this));
View Code
原文地址:https://www.cnblogs.com/hellocjr/p/11712593.html