MD5签名生成 参数名ASCII码从小到大排序

MD5加密是一种常见的加密方式,我们经常用在保存用户密码和关键信息上。那么它到底有什么,又什么好处呢,会被这么广泛的运用在应用开发中。 
  1、什么是MD5 
  MD5加密全程是Message-Digest Algoorithm 5(信息-摘要算法),它对信息进行摘要采集,再通过一定的位运算,最终获取加密后的MD5字符串。 
  例如我们要加密一篇文章,那么我们会随机从每段话或者每行中获取一个字,把这些字统计出来后,再通过一定的运算获得一个固定长度的MD5加密后信息。因此,其很难被逆向破解。
 

MD5算法具有以下特点:

1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。 
2、容易计算:从原数据计算出MD5值很容易。 
3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。 
4、弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。 
5、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。 
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等。

 

MD5是不可逆性


在讲解MD5签名原理之前,必须明白MD5是不可逆的,也就是不可破解的,当然可能稍有了解的人会说MD5可以破解,当然,网上也有一些强大的数据库会把各种数据组合的MD5收集起来形成强大的数据库,能冠军数据库搜索可能一些简单的数据会马上找出某些组合对应的MD5值,但咱说的MD5签名生成是最少32位的数值MD5加密,所以这个破解的可能性是非常非常非常小的。所以这还是比较安全的。

原理


原理很简单,请求方对请求数据按一定的规则排序,加上appkey码一起通过MD5加密生成签名,然后把请求数据和签名发给服务方,服务方拿到数据后,去掉appid和无用的数据,通过appid找到请求方的appkey,然后按同样的规则处理数据,并加上appkey通过MD5加密也生成签名,然后和请求方生成的签名去对比,如果值一样,签名验证通过。

需要的东西


服务商一般会给你一个appid,appkey;同时这两个参数服务商也会保存,这两个形成了你的唯一标识。
appid通过网络传输,而appkey是不在网络上进行传输的,只在生成签名时使用,所以安全性还是比较高的。

MD5生成签名的流程

1. 除去加密数组中的空值和签名参数
2. 对数组排序
3. 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
4. 加上appkey值,对形成的数据进行MD5加密,生成签名

签名生成的通用步骤如下:

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意以下重要规则:

◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

public static void main(String[] args) {
       SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
       //String mfrchant_id="fffff";
       String merchant_id="190010002";
       String business_type="1005";
       String out_trade_no="1400000001";
       String key="3A4BC4A4000CF1B5FFA9E351E6C1539E";
       //parameters.put("mfrchant_id", mfrchant_id);
       parameters.put("merchant_id", merchant_id);
       parameters.put("business_type", business_type);
       parameters.put("out_trade_no",out_trade_no);
       String characterEncoding = "UTF-8";         //指定字符集UTF-8
       String mySign = createSign(characterEncoding,parameters,key);
       //System.out.println("我 的签名是:"+mySign);
   }
public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters,String key){
    StringBuffer sb = new StringBuffer();
    StringBuffer sbkey = new StringBuffer();
    Set es = parameters.entrySet();  //所有参与传参的参数按照accsii排序(升序)
    Iterator it = es.iterator();
    while(it.hasNext()) {
        Map.Entry entry = (Map.Entry)it.next();
        String k = (String)entry.getKey();
        Object v = entry.getValue();
        //空值不传递,不参与签名组串
        if(null != v && !"".equals(v)) {
            sb.append(k + "=" + v + "&");
            sbkey.append(k + "=" + v + "&");
        }
    }
    //System.out.println("字符串:"+sb.toString());
    sbkey=sbkey.append("key="+key);
    System.out.println("字符串:"+sbkey.toString());
    //MD5加密,结果转换为大写字符
    String sign = MD5Util.MD5Encode(sbkey.toString(), characterEncoding).toUpperCase();
    System.out.println("MD5加密值:"+sign);
    return sb.toString()+"sign="+sign;
}

MD5Utils

package com.ykx.transfer.util;

import java.security.MessageDigest;

/**
 * @Author:Starry
 * @Description:
 * @Date:Created in 9:46 2018/4/13
 * Modified By:
 */
public class MD5Utils {

    private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};

    /**
     * MD5加密
     * @param origin 字符
     * @param charsetname 编码
     * @return
     */
    public static String MD5Encode(String origin, String charsetname){
        String resultString = null;
        try{
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if(null == charsetname || "".equals(charsetname)){
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        }catch (Exception e){
        }
        return resultString;
    }


    public static String byteArrayToHexString(byte b[]){
        StringBuffer resultSb = new StringBuffer();
        for(int i = 0; i < b.length; i++){
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    public static String byteToHexString(byte b){
        int n = b;
        if(n < 0){
            n += 256;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigIts[d1] + hexDigIts[d2];
    }

}


原文:https://blog.csdn.net/chenghaibing2008/article/details/79701773 

            https://www.jianshu.com/p/e765a6f9db58

            https://blog.csdn.net/qq_30683329/article/details/80879058 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值