精华内容
下载资源
问答
  • 数据签名——32位MD5加密数据

    千次阅读 2019-01-19 11:56:33
    在http协议中,往往要通过报文头发送一个数据签名,用来确认访问者身份或者检查数据是否是原数据而不是被篡改的数据,我下面说的就是一种对数据进行32位MD5加密制作数据签名的方法:   签名规则:  所有的参数...

             在http协议中,往往要通过报文头发送一个数据签名,用来确认访问者身份或者检查数据是否是原数据而不是被篡改的数据,我下面说的就是一种对数据进行32位MD5加密制作数据签名的方法:

     

    签名规则:

             所有的参数按字母排序,参数名和值用“=”连接,参数之母间加“&”来连接如:

              待加密签名字符串:       nameA=valueA&nameB=valueB&nameC=valueC&nameD=valueD

     

    步骤:

            首先写个实体类来接收保存数据参数:MD5Model.java

    public class MD5Model {
    
    	private String nameD = null;
    	private String nameB = null;
    	private String nameC = null;
    	private String nameA = null;
    
    	public MD5Model(String nameD, String nameB, String nameC, String nameA) {
    		super();
    		this.nameD = nameD;
    		this.nameB = nameB;
    		this.nameC = nameC;
    		this.nameA = nameA;
    	}
    	
    	@Override
    	public String toString() {
    		return "MD5Model [nameD=" + nameD + ", nameB=" + nameB + ", nameC="
    				+ nameC + ", nameA=" + nameA + "]";
    	}
    
    	public String getNameD() {
    		return nameD;
    	}
    	public void setNameD(String nameD) {
    		this.nameD = nameD;
    	}
    	public String getNameB() {
    		return nameB;
    	}
    	public void setNameB(String nameB) {
    		this.nameB = nameB;
    	}
    	public String getNameC() {
    		return nameC;
    	}
    	public void setNameC(String nameC) {
    		this.nameC = nameC;
    	}
    	public String getNameA() {
    		return nameA;
    	}
    	public void setNameA(String nameA) {
    		this.nameA = nameA;
    	}
    	
    	
    }
    

     

    写一个工具类:Md5Util.java

        工具类中包含:

             获取实体类参数并且给参数按照签名规则排序生成待加密签名字符串方法:

    	/**
    	 * 获取实体类拼成的加密字段
    	 * @param classA  传入参数实体类
    	 * @return  待加密字符串
    	 */
    	public static String getSign(Object classA) {
    		Field[] fs = classA.getClass().getDeclaredFields();//获取所有属性
    		String[][] temp = new String[fs.length-1][2]; //用二维数组保存  参数名和参数值
    		for (int i=0; i<fs.length;  i++) {
    			fs[i].setAccessible(true);
    			temp[i][0] = fs[i].getName().toLowerCase(); //获取属性名
    			try {
    				temp[i][1] = (String) fs[i].get(classA);//把属性值放进数组
    			}  catch (Exception e) {
    				System.out.println("【签名字段:"+fs[i].getName()+"添加失败】");
    			} 
    		}
    		temp = doChooseSort(temp); //对参数实体类按照字母顺序排续
    		String result = "";
    		for (int i = 0; i < temp.length; i++) {//按照签名规则生成待加密字符串
    			result = result + temp[i][0]+"="+temp[i][1]+"&";
    		}
    		return result.substring(0, result.length()-1);//消除掉最后的“&”
    	}
    	
    	/**
    	 * 对二维数组里面的数据进行选择排序,按字段名按abcd顺序排列
    	 * @param data 未按照字母顺序排序的二维数组
    	 * @return
    	 */
    	public static String[][] doChooseSort(String[][] data) {//排序方式为选择排序
    		String[][] temp = new String[data.length][2];
    		temp = data;
    		 int n = temp.length;
    	        for (int i = 0; i < n-1; i++) {
    	            int k = i;// 初始化最小值的小标
    	            for (int j = i+1; j<n; j++) {
    	                if (temp[k][0].compareTo(temp[j][0]) > 0) {	//下标k字段名大于当前字段名
    	                    k = j;// 修改最大值的小标
    	                }
    	            }
    	            // 将最小值放到排序序列末尾
    	            if (k > i) {  //用相加相减法交换data[i] 和 data[k]
    	            	String tempValue ;
    	            	tempValue = temp[k][0];
    	            	temp[k][0] = temp[i][0];
    	            	temp[i][0] = tempValue;
    	            	tempValue = temp[k][1];
    	            	temp[k][1] = temp[i][1];
    	            	temp[i][1] = tempValue;
    	            }
    	        }
    		return temp;
    	}

                32位MD5加密方法:

    	/**
    	 * 对字符串进行32位MD5加密
    	 * @param str  待加密字符串
    	 * @return
    	 */
    	public static String EncodeByMD5(String str) {
            try {
                // 生成一个MD5加密计算摘要
                MessageDigest md = MessageDigest.getInstance("MD5");
                // 计算md5函数
                md.update(str.getBytes("UTF-8"));
                // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
                // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
                String md5=new BigInteger(1, md.digest()).toString(16);
                //BigInteger会把0省略掉,需补全至32位
                return fillMD5(md5);
            } catch (Exception e) {
                throw new RuntimeException("MD5加密错误:"+e.getMessage(),e);
            }
        }
    
        private static String fillMD5(String md5){
        	//如果不够32位则回调自身补零,最后返回32位长度的签名
            return md5.length()==32?md5:fillMD5("0"+md5);
        }

     

          测试:

        public static void main(String[] args) throws Exception{
        	//生成参数的实体类
        	MD5Model md5Model  = new MD5Model("valueD","valueB","valueC","valueA");
        	System.out.println("实体类数据:" + md5Model.toString());
        	System.out.println("实体类转化成的待加密的签名字符串:" + Md5Util.getSign(md5Model));
        	System.out.println("加密后的签名字符串:" + Md5Util.EncodeByMD5(Md5Util.getSign(md5Model)));
        } 
    	

           结果:

            

    实体类数据:MD5Model [nameD=valueD, nameB=valueB, nameC=valueC, nameA=valueA]
    实体类转化成的待加密的签名字符串:namea=valueA&nameb=valueB&namec=valueC&named=valueD
    加密后的签名字符串:c4b040eb23ce28d1cc45f771099cb3f6
    

    在通过http协议传输后,对方通过把你传输的参数用同样的规则生成 加密后的签名字符串 ,对比你报文头中的签名,如果相同,则确定数据传输正确,否则则说明在传输过程中你的数据已经被篡改了。

    展开全文
  • 现在应用开发中通常会用到接口,其数据是通过开放的互联网传输,对数据的安全性有一定要求,为了防止数据在传输过程中被篡改,常用数据签名(sign)的方式来校验。数据签名sign生成方法①去除数组中的空值和签名参数...

    PHP接口开发数据签名这个非常的重要不但要有好的算法同时也要保密了,下面我们来看一篇由php实现的关于PHP接口开发数据签名例子吧,具体如下所示。

    现在应用开发中通常会用到接口,其数据是通过开放的互联网传输,对数据的安全性有一定要求,为了防止数据在传输过程中被篡改,常用数据签名(sign)的方式来校验。

    数据签名sign生成方法

    ①去除数组中的空值和签名参数(sign/sign_type)

    ②按键名升序排列数组

    ③把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串

    ④把拼接后的字符串再与安全校验码直接连接起来

    ⑤MD5等加密函数,加密字符串

    示例代码

    class Sign {

    /**

    * 获取数据签名

    *

    * @param  array  $param  签名数组

    * @param  string $code      安全校验码

    * @param  string $sign_type 签名类型

    * @return string        签名字符串

    */

    public static function getSign($param, $code, $sign_type = 'MD5'){

    //去除数组中的空值和签名参数(sign/sign_type)

    $param = self::paramFilter($param);

    //按键名升序排列数组

    $param = self::paramSort($param);

    //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串

    $param_str = self::createLinkstring($param);

    //把拼接后的字符串再与安全校验码直接连接起来

    $param_str = $param_str . $code;

    //创建签名字符串

    return self::createSign($param_str, $sign_type);

    }

    /**

    * 校验数据签名

    *

    * @param  string $sign  接口收到的签名

    * @param  array  $param  签名数组

    * @param  string $code      安全校验码

    * @param  string $sign_type 签名类型

    * @return boolean true正确,false失败

    */

    public static function checkSign($sign, $param, $code, $sign_type = 'MD5'){

    return $sign == self::getSign($param, $code, $sign_type);

    }

    /**

    * 去除数组中的空值和签名参数

    *

    * @param  array $param 签名数组

    * @return array        去掉空值与签名参数后的新数组

    */

    private static function paramFilter($param){

    $param_filter = array();

    foreach ($param as $key => $val) {

    if($key == 'sign' || $key == 'sign_type' || !strlen($val)){

    continue;

    }

    $param_filter[$key] = $val;

    }

    return $param_filter;

    }

    /**

    * 按键名升序排列数组

    *

    * @param  array $param 排序前的数组

    * @return array        排序后的数组

    */

    private static function paramSort($param){

    ksort($param);

    reset($param);

    return $param;

    }

    /**

    * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串

    *

    * @param  array $param 需要拼接的数组

    * @return string       拼接完成以后的字符串

    */

    private static function createLinkstring($param){

    $str = '';

    foreach ($param as $key => $val) {

    $str .= "{$key}={$val}&";

    }

    //去掉最后一个&字符

    $str = substr($str, 0, strlen($str) - 1);

    //如果存在转义字符,那么去掉转义

    if(get_magic_quotes_gpc()){

    $str = stripslashes($str);

    }

    return $str;

    }

    /**

    * 创建签名字符串

    *

    * @param  string $param 需要加密的字符串

    * @param  string $type  签名类型 默认值:MD5

    * @return string 签名结果

    */

    private static function createSign($param, $type = 'MD5'){

    $type = strtolower($type);

    if($type == 'md5'){

    return md5($param);

    }

    if($type == 'dsa'){

    exit('DSA 签名方法待后续开发,请先使用MD5签名方式');

    }

    exit("接口暂不支持" . $type . "类型的签名方式");

    }

    }

    展开全文
  • junit测试 RSA非对称签名和MD5数据签名 java -------------------------AbstractTest----start------------------------------ package com; import java.util.HashMap; import java.util....

    junit测试 RSA非对称签名和MD5数据签名  java


    -------------------------AbstractTest----start------------------------------



    package com;
    import java.util.HashMap;
    import java.util.Map;
    import org.junit.Before;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.web.context.WebApplicationContext;


    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class AbstractTest {

        public MockMvc mvc;
        
        public Map<String, Object> baseMap ;
        
        @Autowired
        WebApplicationContext wac ;
        
    @Before
        public void setup(){
           /*
            * MockMvcBuilders使用构建MockMvc对象.
            */
    baseMap = new HashMap<>() ;
    baseMap.put("param1",1);
    baseMap.put("param2",1);
    baseMap.put("param3","123123213213213213213");
             mvc = MockMvcBuilders.webAppContextSetup(wac).build();
        }
    }

    -------------------------AbstractTest----end------------------------------


    -------------------------SignControllerTest----start------------------------------

    package com.test.controller;
    import java.util.TreeMap;
    import org.junit.Assert;
    import org.junit.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.MediaType;
    import org.springframework.test.web.servlet.MvcResult;
    import org.springframework.test.web.servlet.RequestBuilder;
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    import com.alibaba.fastjson.JSONObject;
    import com.AbstractTest;
    import com.util.StringUtil;
    import com.util.sign.RSAUtils;
    import com.util.sign.RequestUtils;


    public class SignControllerTest extends AbstractTest{
    private final static Logger log = LoggerFactory.getLogger(SignControllerTest.class);


    @Test
    public void testValidSign() throws Exception {


    TreeMap<String, String> params = new TreeMap<String, String>();
    params.put("activityId", "710183692382806016");
    params.put("status", "0");
    params.put("couponName", "优惠券名称0710001");
    params.put("couponType", "1");
    params.put("singleAmt", "10");
    params.put("amtLimit", "500");
    params.put("startTime", "");
    params.put("endTime", "");

    //mothod 2 

    //拼接签名原串
    String paramSrc = RequestUtils.getParamSrc(params);
    log.info("拼接签名原串(paramSrc):" + paramSrc);


    // 原串转码,UTF-8转GBK
    paramSrc = StringUtil.utf8ToUnicode(paramSrc);
    //paramSrc = new String(paramSrc.getBytes(SignConfig.serverEncodeType), SignConfig.serverEncodeType);
     
    log.info("转码后拼接签名串(paramSrc):" + paramSrc);
    //md5签名
    //String sign = MD5Utils.sign(paramSrc);
    //RSA签名
    String sign = RSAUtils.sign(paramSrc.getBytes("GBK"));

    log.info("生成签名(sign):" + sign);
    //rsa加密原串
    String encryptSrc = paramSrc + "&sign=" + sign;//加密原串


    //rsa密串
    String cipherData = RSAUtils.serverPubEncrypt(encryptSrc);
    log.info("生成加密数据(cipherData):" + cipherData);
    JSONObject param = new JSONObject() ;
    param.put("cipherData", cipherData);
            String json = param.toString() ;
            log.info("json格式参数:" + cipherData);
            System.out.println("================================请求开始,入参:"+json);
            RequestBuilder request = MockMvcRequestBuilders.post("/sign/validSign")
    .contentType(MediaType.APPLICATION_JSON_UTF8)
    .header("SESSIONNO", "5qr24lk2k424jk24kj24k24k43")
    .content(json) ;

            MvcResult mvcResult = mvc.perform(request).andReturn() ;
       
            int status = mvcResult.getResponse().getStatus();  
            String content = mvcResult.getResponse().getContentAsString();
            
            Assert.assertTrue("错误,正确的返回值为200", status == 200);  
            Assert.assertFalse("错误,正确的返回值为200", status != 200);  
            
            System.out.println("返回结果:"+status);
            System.out.println(content);
    }
    }

    -------------------------SignControllerTest----end------------------------------


    -------------------------SignController----start------------------------------

    package com.controller;


    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;


    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;


    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;


    import com.alibaba.fastjson.JSON;
    import com.bean.Result;
    import com.common.enums.ReturnCodeEnum;
    import com.common.sign.RSA;
    import com.common.sign.SignConfig;
    import com.common.sign.SignCore;
    import com.controller.vo.UserCouponVo;
    import com.util.StringUtil;
    import com.util.sign.RSAUtils;
    import com.util.sign.RequestUtils;


    @RestController
    @RequestMapping("/sign")
    public class SignController {


    private final static Logger log = LoggerFactory.getLogger(SignController.class);

    @RequestMapping(value="/modifyAct",method=RequestMethod.POST)
    @ResponseBody
    public Result modifyUser(HttpServletRequest request,HttpServletResponse response,@RequestBody UserCouponVo vo){

    Map<String, String> params = new HashMap<String, String>();
    params.put("activityId", vo.getActivityId());
    params.put("status", vo.getStatus());
    params.put("couponName", vo.getCouponName());
    params.put("couponType", vo.getCouponType());
    params.put("singleAmt", vo.getSingleAmt());
    params.put("amtLimit", vo.getAmtLimit());
    params.put("startTime", vo.getStartTime());
    params.put("endTime", vo.getEndTime());

    Map<String, String> sParaNew = SignCore.paraFilter(params);
    //获取待签名字符串
            String preSignStr = SignCore.createLinkString(sParaNew);
            log.info("获取待签名字符串:" + preSignStr);
            String signStr = "";
            if(SignConfig.sign_type.equals("RSA")){
            signStr = RSA.sign(preSignStr,SignConfig.private_key, SignConfig.input_charset);
            }
            if(!StringUtils.isEmpty(vo.getSign()) && !vo.getSign().equals(signStr)){
            return new Result(ReturnCodeEnum.FAIL_SIGN.getCode(), ReturnCodeEnum.FAIL_SIGN.getDesc());
            }
            return new Result(ReturnCodeEnum.SUCCESS.getCode(), ReturnCodeEnum.SUCCESS.getDesc());
            
    }


    @RequestMapping(value = "/validSign", method = RequestMethod.POST)
        @ResponseBody
    public Result validSign(HttpServletRequest request,HttpServletResponse response,@RequestBody  UserCouponVo vo){

    if(StringUtils.isEmpty(vo.getCipherData())){
    return new Result(ReturnCodeEnum.SIGN_NULL.getCode(), ReturnCodeEnum.SIGN_NULL.getDesc());
    }

    log.info("请求参数加密数据串:" + JSON.toJSONString(vo));
    //数据解密
    String responseData = RSAUtils.serverPriDecrypt(vo.getCipherData());
    //封装数据
    HashMap<String, String> map = RequestUtils.parseString(responseData);

    log.info("验签数据串:source ={}" ,map.get("source"));
    try {
    //rsa验签
    if (RSAUtils.verify(map.get("source"), map.get("sign"))) {
    //MD5验签
    //if (MD5Utils.verify(map.get("source"), map.get("sign"))) {
    log.info("rsa验签,验签结果:通过");
    } else {
    log.info("rsa验签,验签结果:未通过");
    }
    } catch (Exception e) {
    log.error("验签异常", e);
    }
    log.info("解密后的请求参数数据:map={}",JSON.toJSONString(map));

    Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
    Map<String, String> paramMap = new HashMap<>();
    while (iter.hasNext()) {
    Map.Entry<String, String> entry = iter.next();
    paramMap.put(entry.getKey(), StringUtil.unicodeToUtf8(entry.getValue()));
    }
    log.info("解密并转码后的数据:map={}",JSON.toJSONString(paramMap));
     
    return new Result(ReturnCodeEnum.SUCCESS.getCode(), ReturnCodeEnum.SUCCESS.getDesc(),paramMap);
     
    }
    }

    -------------------------SignController---end------------------------------



    -------------------------base64----start------------------------------

    public final class Base64 {



        static private final int BASELENGTH = 128;
        static private final int LOOKUPLENGTH = 64;
        static private final int TWENTYFOURBITGROUP = 24;
        static private final int EIGHTBIT = 8;
        static private final int SIXTEENBIT = 16;
        static private final int FOURBYTE = 4;
        static private final int SIGN = -128;
        static private final char PAD = '=';
        static private final boolean fDebug = false;
        static final private byte[] base64Alphabet = new byte[BASELENGTH];
        static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];


        static {
            for (int i = 0; i < BASELENGTH; ++i) {
                base64Alphabet[i] = -1;
            }
            for (int i = 'Z'; i >= 'A'; i--) {
                base64Alphabet[i] = (byte) (i - 'A');
            }
            for (int i = 'z'; i >= 'a'; i--) {
                base64Alphabet[i] = (byte) (i - 'a' + 26);
            }


            for (int i = '9'; i >= '0'; i--) {
                base64Alphabet[i] = (byte) (i - '0' + 52);
            }


            base64Alphabet['+'] = 62;
            base64Alphabet['/'] = 63;


            for (int i = 0; i <= 25; i++) {
                lookUpBase64Alphabet[i] = (char) ('A' + i);
            }


            for (int i = 26, j = 0; i <= 51; i++, j++) {
                lookUpBase64Alphabet[i] = (char) ('a' + j);
            }


            for (int i = 52, j = 0; i <= 61; i++, j++) {
                lookUpBase64Alphabet[i] = (char) ('0' + j);
            }
            lookUpBase64Alphabet[62] = (char) '+';
            lookUpBase64Alphabet[63] = (char) '/';


        }


        private static boolean isWhiteSpace(char octect) {
            return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
        }


        private static boolean isPad(char octect) {
            return (octect == PAD);
        }


        private static boolean isData(char octect) {
            return (octect < BASELENGTH && base64Alphabet[octect] != -1);
        }


        /**
         * Encodes hex octects into Base64
         *
         * @param binaryData
         *            Array containing binaryData
         * @return Encoded Base64 array
         */
        public static String encode(byte[] binaryData) {


            if (binaryData == null) {
                return null;
            }


            int lengthDataBits = binaryData.length * EIGHTBIT;
            if (lengthDataBits == 0) {
                return "";
            }


            int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
            int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
            int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
            char encodedData[] = null;


            encodedData = new char[numberQuartet * 4];


            byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;


            int encodedIndex = 0;
            int dataIndex = 0;
            if (fDebug) {
                System.out.println("number of triplets = " + numberTriplets);
            }


            for (int i = 0; i < numberTriplets; i++) {
                b1 = binaryData[dataIndex++];
                b2 = binaryData[dataIndex++];
                b3 = binaryData[dataIndex++];


                if (fDebug) {
                    System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
                }


                l = (byte) (b2 & 0x0f);
                k = (byte) (b1 & 0x03);


                byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
                byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);


                if (fDebug) {
                    System.out.println("val2 = " + val2);
                    System.out.println("k4   = " + (k << 4));
                    System.out.println("vak  = " + (val2 | (k << 4)));
                }


                encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
                encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
                encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
            }


            // form integral number of 6-bit groups
            if (fewerThan24bits == EIGHTBIT) {
                b1 = binaryData[dataIndex];
                k = (byte) (b1 & 0x03);
                if (fDebug) {
                    System.out.println("b1=" + b1);
                    System.out.println("b1<<2 = " + (b1 >> 2));
                }
                byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
                encodedData[encodedIndex++] = PAD;
                encodedData[encodedIndex++] = PAD;
            } else if (fewerThan24bits == SIXTEENBIT) {
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                l = (byte) (b2 & 0x0f);
                k = (byte) (b1 & 0x03);


                byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);


                encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
                encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
                encodedData[encodedIndex++] = PAD;
            }


            return new String(encodedData);
        }


        /**
         * Decodes Base64 data into octects
         *
         * @param encoded
         *            string containing Base64 data
         * @return Array containind decoded data.
         */
        public static byte[] decode(String encoded) {


            if (encoded == null) {
                return null;
            }
            char[] base64Data = encoded.toCharArray();
            // remove white spaces
            int len = removeWhiteSpace(base64Data);


            // if (len % FOURBYTE != 0) {
            // return null;// should be divisible by four
            // }


            int numberQuadruple = (len / FOURBYTE);


            if (numberQuadruple == 0) {
                return new byte[0];
            }


            byte decodedData[] = null;
            byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
            char d1 = 0, d2 = 0, d3 = 0, d4 = 0;


            int i = 0;
            int encodedIndex = 0;
            int dataIndex = 0;
            decodedData = new byte[(numberQuadruple) * 3];


            for (; i < numberQuadruple - 1; i++) {


                if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
                        || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) {
                    return null;
                } // if found "no data" just return null


                b1 = base64Alphabet[d1];
                b2 = base64Alphabet[d2];
                b3 = base64Alphabet[d3];
                b4 = base64Alphabet[d4];


                decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
            }


            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
                return null;// if found "no data" just return null
            }


            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];


            d3 = base64Data[dataIndex++];
            d4 = base64Data[dataIndex++];
            if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
                if (isPad(d3) && isPad(d4)) {
                    if ((b2 & 0xf) != 0) // last 4 bits should be zero
                    {
                        return null;
                    }
                    byte[] tmp = new byte[i * 3 + 1];
                    System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                    tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    return tmp;
                } else if (!isPad(d3) && isPad(d4)) {
                    b3 = base64Alphabet[d3];
                    if ((b3 & 0x3) != 0) // last 2 bits should be zero
                    {
                        return null;
                    }
                    byte[] tmp = new byte[i * 3 + 2];
                    System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                    tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                    tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                    return tmp;
                } else {
                    return null;
                }
            } else { // No PAD e.g 3cQl
                b3 = base64Alphabet[d3];
                b4 = base64Alphabet[d4];
                decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);


            }


            return decodedData;
        }


        /**
         * remove WhiteSpace from MIME containing encoded Base64 data.
         *
         * @param data
         *            the byte array of base64 data (with WS)
         * @return the new length
         */
        private static int removeWhiteSpace(char[] data) {
            if (data == null) {
                return 0;
            }


            // count characters that's not whitespace
            int newSize = 0;
            int len = data.length;
            for (int i = 0; i < len; i++) {
                if (!isWhiteSpace(data[i])) {
                    data[newSize++] = data[i];
                }
            }
            return newSize;
        }

    }

    -------------------------base64----end------------------------------

    -------------------------MD5----start------------------------------

    package com.util.sign;


    import java.security.MessageDigest;


    import com.util.GetParamConfig;
    /**
     * 类名: MD5Utils</br> 
     * 描述: 数据签名MD5加密  
     */
    public class MD5Utils {


        /**
         * MD5签名
         * 
         * @param paramSrc
         *            the source to be signed
         * @return
         * @throws Exception
         */
        public static String sign(String paramSrc) {
        String key = "";
    try {
    key = GetParamConfig.getParam("sign.key");
    } catch (Exception e) {
    e.printStackTrace();
    }
            String sign = md5(paramSrc + "&key=" + key);
            System.out.println("MD5签名结果:" + sign);
            return sign;
        }


        /**
         * MD5验签
         * 
         * @param source
         *            签名内容
         * @param sign
         *            签名值
         * @return
         */
        public static boolean verify(String source, String signStr) {
        String key = "";
    try {
    key = GetParamConfig.getParam("sign.key");
    } catch (Exception e) {
    e.printStackTrace();
    }
            String sign = md5(source + "&key=" + key);
            System.out.println("自签结果:" + sign);
            return signStr.equals(sign);
        }


        public final static String md5(String paramSrc) {
            char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
            try {
                byte[] btInput = paramSrc.getBytes("utf-8");
                // 获得MD5摘要算法的 MessageDigest 对象
                MessageDigest mdInst = MessageDigest.getInstance("MD5");
                // 使用指定的字节更新摘要
                mdInst.update(btInput);
                // 获得密文
                byte[] md = mdInst.digest();
                // 把密文转换成十六进制的字符串形式
                int j = md.length;
                char str[] = new char[j * 2];
                int k = 0;
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    str[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(str).toLowerCase();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    -------------------------MD5----end------------------- 

    -------------------------requestutil --- start-----------

    package com.util.sign;


    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.HashMap;
    import java.util.TreeMap;


    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import org.springframework.util.StringUtils;


    import com.common.sign.SignConfig;


    public class RequestUtils {


        /**
         * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
         */
        public static String getParamSrc(TreeMap<String, String> paramsMap) {
            StringBuffer paramstr = new StringBuffer();
            for (String pkey : paramsMap.keySet()) {
                String pvalue = paramsMap.get(pkey);
                if (!StringUtils.isEmpty(pvalue)) {// 空值不传递,不签名
                    paramstr.append(pkey + "=" + pvalue + "&"); // 签名原串,不url编码
                }
            }
            // 去掉最后一个&
            String result = paramstr.substring(0, paramstr.length() - 1);
            System.out.println("签名原串:" + result);
            return result;
        }


        /**
         * 分解解密后的字符串,保存为map
         */
        public static HashMap<String, String> parseString(String responseData) {
            HashMap<String, String> map = new HashMap<String, String>();
            String[] s1 = responseData.split("&");
            String[] s2 = new String[2];
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < s1.length; i++) {
                s2 = s1[i].split("=", 2);
                map.put(s2[0], s2[1]);
                if (!s2[0].equals("sign")) {
                    sb.append(s2[0] + "=" + s2[1] + "&");
                }
            }
            String source = sb.substring(0, sb.length() - 1);
            map.put("source", source);
            return map;
        }


        /**
         * 解析xml
         */
        public static String getXmlElement(String responseData, String element) {
            String result = null;


            try {
                Document dom = DocumentHelper.parseText(responseData);
                Element root = dom.getRootElement();
                result = root.element(element).getText();
            } catch (DocumentException e1) {
                e1.printStackTrace();
            }
            return result;
        }


        public static String doPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(conn.getOutputStream());
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), SignConfig.serverEncodeType));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送 POST 请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输出流、输入流
            finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return result;
        }
    }

    -------------------requestutil ---end -----------------------


    --------------RSAUtil ---------------start --------------

    package com.util.sign;


    import java.io.ByteArrayOutputStream;
    import java.security.Key;
    import java.security.KeyFactory;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Arrays;


    import javax.crypto.Cipher;


    import com.common.sign.SignConfig;
    import com.util.GetConfig;




    /**
     * 类名: RSAUtils</br>
     
     * 描述: RSA数据签名和加解密 
     */
    public class RSAUtils {


        /**
         * 加密算法RSA
         */
        public static final String KEY_ALGORITHM = "RSA";


        /**
         * 签名算法
         */
        public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA";


        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 117;


        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 128;


        /**
         * RSA签名,目前服务端未支持
         * 
         * @param paramSrc
         *            the source to be signed
         * @return
         */
        public static String sign(byte[] data) throws Exception {
            byte[] digest = sha1(data);
            String PRIVATE_KEY = "";
    try {
    PRIVATE_KEY = GetParamConfig.getParam("CLIENT_PRIVATE_KEY");
    } catch (Exception e) {
    e.printStackTrace();
    }
            byte[] encryptData = encryptByPrivateKey(digest, PRIVATE_KEY);
            return Base64.encode(encryptData);
        }


        /**
         * RSA验签
         * 
         * @param source
         *            签名内容
         * @param sign
         *            签名值
         * @return
         */
        public static boolean verify(String source, String sign) throws Exception {
            byte[] digest = sha1(source.getBytes("GBK"));
            String CLIENT_PUBLIC_KEY = "";
    try {
    CLIENT_PUBLIC_KEY = GetParamConfig.getParam("CLIENT_PUBLIC_KEY");
    } catch (Exception e) {
    e.printStackTrace();
    }
            byte[] encryptData = decryptByPublicKey(Base64.decode(sign), CLIENT_PUBLIC_KEY);
            if (Arrays.equals(digest, encryptData)) {
                return true;
            } else {
                return false;
            }
        }


        /**
         * 生成签名摘要
         * 
         * @param data
         * @return
         * @throws NoSuchAlgorithmException
         */
        private static byte[] sha1(byte[] data) throws NoSuchAlgorithmException {
            MessageDigest md = null;
            md = MessageDigest.getInstance("SHA-1"); // 选择SHA-1,也可以选择MD5
            byte[] digest = md.digest(data); // 返回的是byet[],要转化为String存储比较方便
            return digest;
        }


        /**
         * RSA加密
         * 
         * @param paramstr
         * @return
         */
        public static String clientPubEncrypt(String paramstr) {
        try {
        String PUBLIC_KEY = "";
        PUBLIC_KEY = GetParamConfig.getParam("CLIENT_PUBLIC_KEY");
        byte[] cipherData = RSAUtils.encryptByPublicKey(paramstr.getBytes("UTF-8"), PUBLIC_KEY);
        String result = Base64.encode(cipherData);
        System.out.println("加密结果:" + result);
        return result;
        } catch (Exception e) {
        e.printStackTrace();
        }
        return null;
        }
        
        


        /**
         * RSA解密
         * 
         * @param cipherData
         *            the data to be decrypt
         * @return decryptByPrivateKey
         */
        public static String clientPriDecrypt(String cipherData) {
            try {
            String PRIVATE_KEY = "";
            PRIVATE_KEY = GetParamConfig.getParam("CLIENT_PRIVATE_KEY"); 
                byte[] cipher = RSAUtils.decryptByPrivateKey(Base64.decode(cipherData), PRIVATE_KEY);
                String result = new String(cipher,SignConfig.serverEncodeType);
                System.out.println("解密结果:" + new String(result.getBytes("GBK"), "GBK"));
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /**
         * RSA加密
         * 
         * @param paramstr
         * @return
         */
        public static String serverPubEncrypt(String paramstr) {
            try {
            String PUBLIC_KEY = "";
            PUBLIC_KEY = GetParamConfig.getParam("SERVER_PUBLIC_KEY");
                byte[] cipherData = RSAUtils.encryptByPublicKey(paramstr.getBytes("UTF-8"), PUBLIC_KEY);
                String result = Base64.encode(cipherData);
                System.out.println("加密结果:" + result);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /**
         * RSA解密
         * 
         * @param cipherData
         *            the data to be decrypt
         * @return decryptByPrivateKey
         */
        public static String serverPriDecrypt(String cipherData) {
        try {
        String PRIVATE_KEY = "";
        PRIVATE_KEY = GetParamConfig.getParam("SERVER_PRIVATE_KEY"); 
        byte[] cipher = RSAUtils.decryptByPrivateKey(Base64.decode(cipherData), PRIVATE_KEY);
        String result = new String(cipher,SignConfig.serverEncodeType);
        System.out.println("解密结果:" + new String(result.getBytes("GBK"), "GBK"));
        return result;
        } catch (Exception e) {
        e.printStackTrace();
        }
        return null;
        }


        /**
         * <P>
         * 私钥解密
         * </p>
         * 
         * @param data
         *            要解密的数据
         * @param privateKey
         *            私钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {
            byte[] keyBytes = Base64.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        }


        /**
         * <p>
         * 公钥解密
         * </p>
         * 
         * @param data
         *            要解密的数据
         * @param publicKey
         *            公钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPublicKey(byte[] data, String publicKey) throws Exception {
            byte[] keyBytes = Base64.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        }


        /**
         * <p>
         * 公钥加密
         * </p>
         * 
         * @param data
         *            源数据
         * @param publicKey
         *            公钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
            byte[] keyBytes = Base64.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }


        /**
         * <p>
         * 私钥加密
         * </p>
         * 
         * @param data
         *            源数据
         * @param privateKey
         *            私钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
            byte[] keyBytes = Base64.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }

    }
    --------------RSAUitl ---------------end ---------------

    ------------------GetConfig -----------start ------------

    package com.util;
    /**
     * 
     * 
     * @Package: com.subscription.util  
     * @ClassName: GetConfig 
     * @Description: 获取Conf.properties 里面的参数
     */
    public class GetConfig {
       
        public static String getParam(String key) { 
            return ConfigUtil.getProperty(key); 
       
        }
        
    }

    ------------------GetConfig -----------start ------------


    ------------------ConfigUtil -----------start ------------


     package com.util;


    import javax.annotation.PostConstruct;


    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.env.Environment;
    import org.springframework.stereotype.Component;


    /**
     * 
     * 
     * @Package: com.common.util  
     * @ClassName: ConfigUtil 
     * @Description: TODO 
     */
    @Component
    public class ConfigUtil {


    @Autowired
    private Environment env;
        
        private static Environment localEnv;
        
        @PostConstruct
        public void init() {
        localEnv = this.env;
       
        }
        public static int getIntProperty(String key){
        return Integer.parseInt(localEnv.getProperty(key)) ;
        }
        
        
        public static String getProperty(String key){
        return localEnv.getProperty(key) ;
        }
       
        public static String getProperty(String key,String def){
        if (StringUtils.isBlank(localEnv.getProperty(key))) {
    return def ;
    }
        return localEnv.getProperty(key) ;
        }


    }

    ---------------------ConfigUtil -----------end ------------


    展开全文
  • 签名算法将所有请求参数(key,value 为一组),对数据结构按照 key 的升序,重新排序, 需要对 ...MD5 加密将新的字符串,统一为大写字符串将生成好的字符串加上“私钥”,形成新的字符串(私钥为 ONex-OMS 系统里面生...

    签名算法

    将所有请求参数(key,value 为一组),对数据结构按照 key 的升序,重新排序, 需要对 null 值进行过滤,需要将 boolean 型进行转换为 1 和 0

    将排序后参数组合为新的字符串(keyvaluekeyvalue 中间无分割符)

    将生成好的字符串进行 MD5 加密

    将新的字符串,统一为大写字符串

    将生成好的字符串加上“私钥”,形成新的字符串(私钥为 ONex-OMS 系统里面生成)

    再进行一次 MD5 加密,得到加密后的字符串

    再统一为大写字符串,得到最终的签名字符串 注意:从“系统级参数”开始到“业务级参数”全部作为请求参数.sign 可以不算入,如果 放进去,开始 sign = null ,也会被过滤掉的

    package net.wit.util;

    import java.io.UnsupportedEncodingException;

    import java.net.URLDecoder;

    import java.net.URLEncoder;

    import java.util.Enumeration;

    import java.util.HashMap;

    import java.util.Map;

    import java.util.Map.Entry;

    import java.util.Set;

    import java.util.TreeMap;

    import javax.servlet.http.HttpServletRequest;

    import org.apache.commons.codec.digest.DigestUtils;

    /**

    * 类MD5Sign.java的实现描述:MD5签名和验签

    *

    *

    */

    public class MD5Sign {

    /**

    * 方法描述:将字符串MD5加码 生成32位md5码

    *

    * [@author](https://my.oschina.net/arthor) leon 2016年10月10日 下午3:02:30

    * [@param](https://my.oschina.net/u/2303379) inStr

    * [@return](https://my.oschina.net/u/556800)

    */

    public static String md5(String inStr) {

    try {

    return DigestUtils.md5Hex(inStr.getBytes("UTF-8"));

    } catch (UnsupportedEncodingException e) {

    throw new RuntimeException("MD5签名过程中出现错误");

    }

    }

    /**

    * 方法描述:签名字符串

    *

    *

    * [@param](https://my.oschina.net/u/2303379) params 需要签名的参数

    * [@param](https://my.oschina.net/u/2303379) appSecret 签名密钥

    * @return

    */

    public static String sign(HashMap params, String appSecret) {

    StringBuilder valueSb = new StringBuilder();

    params.put("appSecret", appSecret);

    // 将参数以参数名的字典升序排序

    Map sortParams = new TreeMap(params);

    Set> entrys = sortParams.entrySet();

    // 遍历排序的字典,并拼接value1+value2......格式

    for (Entry entry : entrys) {

    valueSb.append(entry.getValue());

    }

    params.remove("appSecret");

    return md5(valueSb.toString());

    }

    /**

    * 方法描述:验证签名

    *

    *

    * @param appSecret 加密秘钥

    * @param request

    * @return

    * @throws Exception

    */

    public static boolean verify(String appSecret, HttpServletRequest request) throws Exception {

    String sign = request.getParameter("sign");

    if (sign == null) {

    throw new Exception(URLDecoder.decode("请求中没有带签名","UTF-8"));

    }

    if (request.getParameter("timestamp") == null) {

    throw new Exception(URLDecoder.decode("请求中没有带时间戳","UTF-8"));

    }

    Long timestamp=Long.parseLong(request.getParameter("timestamp"));

    Long second = (System.currentTimeMillis() - timestamp) / (1000 * 60);

    if(second>10){

    throw new Exception(URLDecoder.decode("timestamp有效期超过十分钟","UTF-8"));

    }

    HashMap params = new HashMap();

    // 获取url参数

    @SuppressWarnings("unchecked")

    Enumeration enu = request.getParameterNames();

    while (enu.hasMoreElements()) {

    String paramName = enu.nextElement().trim();

    if (!paramName.equals("sign")) {

    // 拼接参数值字符串并进行utf-8解码,防止中文乱码产生

    params.put(paramName, URLDecoder.decode(request.getParameter(paramName), "UTF-8"));

    }

    }

    //params.put("appSecret", appSecret);

    // 将参数以参数名的字典升序排序

    Map sortParams = new TreeMap(params);

    Set> entrys = sortParams.entrySet();

    // 遍历排序的字典,并拼接value1+value2......格式

    StringBuilder valueSb = new StringBuilder();

    for (Entry entry : entrys) {

    valueSb.append(entry.getValue());

    }

    String mysign = md5(md5(valueSb.toString().toUpperCase().toString()+appSecret)).toUpperCase().toString();

    if (mysign.equals(sign)) {

    return true;

    } else {

    throw new Exception(URLDecoder.decode("签名不正确","UTF-8"));

    }

    }

    }

    展开全文
  • 签名算法将所有请求参数(key,value 为一组),对数据结构按照 key 的升序,重新排序, 需要对 ...MD5 加密将新的字符串,统一为大写字符串将生成好的字符串加上“私钥”,形成新的字符串(私钥为 ONex-OMS 系统里面生...
  • 1、HMAC-MD5 HMAC-MD5签名算法,采用MD5作为散列函数,...防止数据在传输过程中被篡改,通过HMAC-MD5 签名算法校验数据。验证流程: 得到请求方传过来的签名sig->自己拿到请求体后,再按双方约定的协议生成一个...
  • 自己编的md5,可以加密超大数据的文本,用来理解MD5的算法相当不错
  • 原来在Eclipse中获取SHA1或者MD5,在IDE界面上就可以查找到。 切换到Android Studio后,如何查看呢?找了半天没找到。那就老办法命令行。 第一步、打开Android Studio的Tools->Open Terminal...(新版本已经调整了...
  • 在前端用js定义md5函数对值做哈希,如此用户提交表单后,在网络中路由间传递的便是简单加密后的信息,而非明文信息,等表单提交到后台后,可用md5再次对其进行加密,再行存储。亦或者防止有人截取报文修改客户端提交...
  • 分享给大家供大家参考,具体如下:class Md5RSA{/*** 利用约定数据和私钥生成数字签名* @param $data 待签数据* @return String 返回签名*/public function sign($data=''){if (empty($data)){return False;...
  • java md5签名

    2019-09-17 21:44:21
    签名算法 将所有请求参数(key,value 为一组),对数据结构按照 key 的升序,重新排序, 需要对 null 值进行过滤,需要将 boolean 型进行转换为 1 和 0 将排序后参数组合为新的字符串...将生成好的字符串进行 MD5 加...
  • 本资源包含一套成型的dll库,只需拷贝里面的include/lib/...里面涵盖常用的数据加密算法(RSA/DES),数据签名MD5/CRC32/SHA1),源代码暂不开放(主要对网上的代码,做得二次封装,爬坑及优化,哈哈哈哈……)
  • MD5 电子签名

    2016-03-22 09:27:54
    MD5 算法假设我们有 b - bits 的数据,需要计算他的电子签名 , 对于任意的 b ( 甚至可以是 0 , 但是必须是 8 的倍数) 。追加对齐bit数据。让数据对齐成 模512 byte 剩余448 byte 的长度。 追加数据一定要进行,...
  • 一,前序今天在学习sign签名的的时候,了解了下常用的...二,加密业务规则签名生成的通用步骤如下:第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序...
  • 一.背景为了增加接口的安全性(防止中间人攻击),现... 签名生成步骤①设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&...
  • MD5是一种常用的哈希算法,主要用于对一些重要数据进行“签名”,当然这些数据可以是任意的。最终得到的“签名”通常都是一个16或32位的十六进制的字符串。 实际工作开发中,是不会有人直接将密码明文直接放到数据库...
  • MD5接口签名认证

    千次阅读 2018-07-19 18:33:58
    我方位数据源,与三方做数据对接要做的两件事情 1.因三方pull数据需要三方提供生产环境 IP 地址,我方配置...通常会用MD5数据签名认证 1.三方对请求参数做按字段顺序排序做加密 Map&lt;String,String&...
  • MD5 数据加密

    2018-06-11 17:35:37
    MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)
  • python实现MD5签名和验签

    千次阅读 2019-04-28 22:40:23
    请求方对请求数据按一定的规则排序,加上appkey码一起通过MD5加密生成签名,然后把请求数据签名发给服务方,服务方拿到数据后,找到请求方的appkey,然后按同样的规则处理数据,并加上appkey通过MD5加密也生成签名...
  • md5介绍:MD5是一种常用的哈希算法,主要用于对一些重要数据进行“签名”,当然这些数据可以是任意的。最终得到的“签名”通常都是一个16或32位的十六进制的字符串。 实际工作开发中,是不会有人直接将密码明文直接...
  • 签名就是对原始数据MD5加密后的字节序列。而原始数据就是普通的string字符串。 2.服务器端呢:将收到的原始数据,进行MD5加密后得到字节序列,将这个字节序列与传输过来的sign的value,进行对比。如果俩sign值一样...
  • md5只是用来签名签名的作用是保证数据完整不会被破坏而已,多一个sign标签,sign的值就是md5生成的字符串。签名和加密是两回事
  • md5介绍:MD5是一种常用的哈希算法,主要用于对一些重要数据进行“签名”,当然这些数据可以是任意的。最终得到的“签名”通常都是一个16或32位的十六进制的字符串。 实际工作开发中,是不会有人直接将密码明文...
  • MD5加密有哪些特点? 压缩性:任意长度的数据,算出的MD5值长度... 强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。 MD5应用场景: 一致性验证 数字签名 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,068
精华内容 427
关键字:

数据签名md5