美文网首页
项目中接口传输的参数加密

项目中接口传输的参数加密

作者: 8ba406212441 | 来源:发表于2018-09-07 09:16 被阅读407次

    一,数据加密方式

    BASE64:编码方式(8位字节代码),二进制与字符串相互转换

    MD5:Message Algorithm(消息摘要算法第五版),散列函数(哈希算法)_不可逆,压缩性

    DES:Data Encrytion Standard(数据加密标准),对应算法是DEA

    特点:1. 对称加密 2. 同一个SK
    

    AES:Advanced Encrytion Standard(高级加密标准)

       特点:1. 对称加密 2. 一个SK扩展成多个子SK,轮加密
    

    RSA:特点:
    1. 非对称加密,即:PK与SK不是同一个
    2. PK用于加密,SK用于解密
    3. PK决定SK,但是PK很难算出SK(数学原理:两个大质数相乘,积很难因式分解)
    4. 速度慢,只对少量数据加密

    DES加密:

    DES加密.png

    AES加密:

    AES加密.png

    RSA加密:

    RSA加密.png

    SSL使用RSA:

    SSL使用RSA.png

    加密相关方法及api

    1,MessageDigest是Java自带的类

    MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
    MessageDigest 对象开始被初始化。该对象通过使用 update()方法处理数据。任何时候都可以调用 reset()方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用digest() 方法之一完成哈希计算。

    2,Java cipher加密与解密

    https://blog.csdn.net/sweetgirl520/article/details/78189742
    ENCRYPT_MODE,加密数据
    DECRYPT_MODE,解密数据
    WRAP_MODE,将一个Key封装成字节,可以用来进行安全传输
    UNWRAP_MODE,将前述已封装的密钥解开成java.security.Key对象

    3,SecretKeySpec类

    SecretKeySpec类是KeySpec接口的实现类,用于构建秘密密钥规范。可根据一个字节数组构造一个SecretKey.
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");//// 定义加密算法,通过AES算法得到的密钥

    4, IvParameterSpec

    如果加密时采用DES/CBC/PKCS5Padding时,且使用了:
    IvParameterSpec iv = new IvParameterSpec("12345678".getBytes("UTF-8"));

    https://blog.csdn.net/jjwwmlp456/article/details/20960029

    二,项目中的加密

    例一:

    接口传输的参数只支持两个参数“si”和“pa”。
    “si”:使用的是MD5进行加密的校验码。
    “pa”:使用的是BASE64进行加密的参数逻辑码
    参数传递以及数据返回格式统一采用Json的方式进行传输。
    如:http://{域名}/api/{接口标识}/{接口方法}?si={MD5}&pa={BASE64}

    JSONObject paObject //所有的请求参数
    HashMap<String, String> param = new HashMap<String, String>();
      Iterator<String> it = paObject.keys();
            while (it.hasNext()) {
                String key = it.next().toString();
                param.put(key, paObject.getString(key));
            }
    
    
    String si = DetectTool.getSign(param);
    String pa = EncryptUtil.encrypt(paObject.toString());
    
    //MD5加密
    
    public static String getSign(HashMap<String,String> params){
    
            Log.e("11111111111111111", params.toString());
             // 先将参数以其参数名的字典序升序进行排序
            Map<String, String> sortedParams = new TreeMap<String, String>(params);
            Set<Entry<String, String>> entrys = sortedParams.entrySet();
    
    
            // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
            StringBuilder basestring = new StringBuilder();
            for (Entry<String, String> param : entrys) {
                basestring.append(param.getKey()).append("=").append(param.getValue());
            }
            Log.e("11111111111111111", basestring.toString());
            /*****************对排序后的参数进行MD5散列函数运算***********************/
            byte[] hash;
    
            try {
                hash = MessageDigest.getInstance("MD5").digest(basestring.toString().getBytes("UTF-8"));
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("Huh, MD5 should be supported?", e);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("Huh, UTF-8 should be supported?", e);
            }
    
            StringBuilder hex = new StringBuilder(hash.length * 2);
            for (byte b : hash) {
                if ((b & 0xFF) < 0x10) hex.append("0");
                hex.append(Integer.toHexString(b & 0xFF));
            }
            /*****************对排序后的参数进行MD5散列函数运算***********************/
            //返回md5加密后的字符串注意统一转化为大写
            return hex.toString().toUpperCase();
    
        }
    
    
    //base64 加密
    
    public static String encrypt(String input) throws Exception {
            return base64Encode(desEncrypt(input.getBytes()));
        }
    
    
    private static String base64Encode(byte[] s) {
            if (s == null) {
                return null;
            }
            BASE64Encoder b = new BASE64Encoder();
            return b.encode(s);
        }
    

    例二:

    接口参数 Sign 类型String : 接口签名,验证请求是否合法
    接口参数 params 类型String : AES加密的json字符串,封装了所有的参数Json格式为 {“account”:”tome”,”password”,”123456”}

    //map转string
    String paramsJson = new Gson().toJson(paramMap);
    //获取时间戳
    String timeStamp = getTimeStampStr();
    
    //请求参数
    Map<String, String> params = new HashMap<>();
            params.put("sign", getSign(timeStamp, paramsJson));
            params.put("timeStamp", timeStamp);
            params.put("params", encrypt(paramsJson));
    
    
         // 数据加密密钥
        private static final String KEY = "~!]'/78m[;.QWEh6";
         //生成签名的干扰盐值
        private static final String SALT = "~!QAZpl,123sdd4jbr5IJN@#,./[;.[]";
         // 初始化向量
        private static final String IV = "=RFGpl,$%^098xbg";
    
    //
     private String getSign(String timeStamp, String paramsJson) {
            String str = timeStamp + SALT + paramsJson;
            return MD5Util.getMD5(str).toUpperCase();
        }
    
    
    //对字符串md5加密
    public static String getMD5(String str) {
            byte[] hash = null;
            try {
                hash = MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8"));
            } catch (NoSuchAlgorithmException e) {
    
            } catch (UnsupportedEncodingException e) {
    
            }
    
            StringBuilder hex = new StringBuilder(hash.length * 2);
            for (byte b : hash) {
                if ((b & 0xFF) < 0x10) hex.append("0");
                hex.append(Integer.toHexString(b & 0xFF));
            }
            return hex.toString();
        }
    
    //方法二: md5加密
    public final static String MD5(String s, String encodingType) {
            char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    
            try {
                // 按照相应编码格式获取byte[]
                byte[] btInput = s.getBytes(encodingType);
                // 获得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);
            } catch (Exception e) {
                return "-1";
            }
        }
    
    // AES加密的json字符串
     private String encrypt(String paramsJson) {
            String enValue = "";
            try {
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                byte[] raw = KEY.getBytes();
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                IvParameterSpec ips = new IvParameterSpec(IV.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ips);
                byte[] encrypted = cipher.doFinal(paramsJson.getBytes("utf-8"));
                enValue = Base64.encodeToString(encrypted, Base64.DEFAULT);// 此处使用BASE64做转码。
            } catch (Exception e) {
                e.printStackTrace();
            }
            return enValue;
        }
    
    //获取时间戳
     protected String getTimeStampStr() {
            return String.valueOf(DateFormatUtils.formatDate(new Date().getTime(), "yyyy-MM-dd HH:mm:ss"));
        }
    
    ===================请求加密的参数======================    
        token:756CDE7185783065638C9DCB142F00F1  
        params:yfOCeqjjrgFIWNffMVVMDQ==
            
        timeStamp:2018-09-06 13:46:31   
        sign:FC9714BA81403836D0D75D23465C7ACF   
        ===================请求加密的参数======================    
    

    例三:

    参数传递以及数据返回格式统一采用Json的方式进行传输。

    签名说明:服务器获取请求参数后,排除掉sign参数后, 对剩下所有参数按照参数名进行升序排序,然后构造成a=1&b=2&c=3&d=4格式后, 进行MD5加密

    //所有的参数json
    JSONObject  paObject = getPaObject(params);
    
      HashMap<String, String> map      = new HashMap<String, String>();
           
            Iterator<String>   it    = paObject.keys();
            while (it.hasNext()) {
                String key = it.next();
                map.put(key, paObject.getString(key));
            }
    
             /****************数据加密*****************/
            String si = DetectTool.getSign(map);
            String pa = DetectTool.getPara(paObject);
            /****************数据加密*****************/
    
    
    //okthhp网络请求
    FormBody.Builder encodingBuilder = new FormBody.Builder();
                Iterator<String> iterator  = paObject.keys();
                while (iterator.hasNext()) {
                    String key = iterator.next();
                    encodingBuilder.add(key, paObject.getString(key));
                }
                encodingBuilder.add("sign", si);
                encodingBuilder.add("param", paObject.toString());
    
                RequestBody body = encodingBuilder.build();
    
                builder.url(url);
                builder.post(body);
    
        public static String getSign(Map<String, String> params) {
    
            // 先将参数以其参数名的字典序升序进行排序
            Map<String, String>            sortedParams = new TreeMap<String, String>(params);
            Set<Map.Entry<String, String>> entrys       = sortedParams.entrySet();
    
    
            // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
            StringBuilder basestring = new StringBuilder();
            for (Map.Entry<String, String> param : entrys) {
                basestring.append(param.getKey()).append("=").append(param.getValue());
            }
            /*****************对排序后的参数进行MD5散列函数运算***********************/
            String hex = EncryptUtils.encryptMD5ToString(basestring.toString());
            /*****************对排序后的参数进行MD5散列函数运算***********************/
            //返回md5加密后的字符串注意统一转化为大写
            return hex.toString().toUpperCase();
    
        }
    
    
       /**
         * MD5加密
         *
         * @param data 明文字符串
         * @return 16进制密文
         */
        public static String encryptMD5ToString(String data) {
            return encryptMD5ToString(data.getBytes());
        }
    
        /**
         * MD5加密
         *
         * @param data 明文字节数组
         * @return 16进制密文
         */
        public static String encryptMD5ToString(byte[] data) {
            return ConvertUtils.bytes2HexString(encryptMD5(data));
        }
    
      /**
         * MD5加密
         *
         * @param data 明文字节数组
         * @return 密文字节数组
         */
        public static byte[] encryptMD5(byte[] data) {
            return hashTemplate(data, "MD5");
        }
    
      /**
         * hash加密模板
         *
         * @param data      数据
         * @param algorithm 加密算法
         * @return 密文字节数组
         */
        private static byte[] hashTemplate(byte[] data, String algorithm) {
            if (data == null || data.length <= 0) return null;
            try {
                MessageDigest md = MessageDigest.getInstance(algorithm);
                md.update(data);
                return md.digest();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return null;
            }
        }
    
      /**
         * MD5加密
         *
         * @param data 明文字节数组
         * @return 16进制密文
         */
        public static String encryptMD5ToString(byte[] data) {
            return ConvertUtils.bytes2HexString(encryptMD5(data));
        }
    
        /**
         * byteArr转hexString
         * <p>例如:</p>
         * bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns 00A8
         *
         * @param bytes 字节数组
         * @return 16进制大写字符串
         */
        public static String bytes2HexString(byte[] bytes) {
            if (bytes == null) return null;
            int len = bytes.length;
            if (len <= 0) return null;
            char[] ret = new char[len << 1];
            for (int i = 0, j = 0; i < len; i++) {
                ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
                ret[j++] = hexDigits[bytes[i] & 0x0f];
            }
            return new String(ret);
        }
    
    
      public static String getPara(@NonNull JSONObject paObject) {
            return EncryptUtils.encryptDES2Base64(paObject.toString());
        }
    //秘钥
    public static String strkey = "12345678";
    
       /**
         * DES加密后转为Base64编码字符串,使用默认秘钥
         *
         * @param input 明文
         * @return
         */
        public static String encryptDES2Base64(String input) {
            return EncodeUtils.base64Encode2String(encryptDES(input.getBytes(), strkey));
        }
    
    /**
         * des加密
         *
         * @param datasource byte[]
         * @param password   String
         * @return byte[]
         */
        public static byte[] encryptDES(byte[] datasource, String password) {
            try {
                SecureRandom random = new SecureRandom();
                DESKeySpec   desKey = new DESKeySpec(password.getBytes());
                //创建一个密匙工厂,然后用它把DESKeySpec转换成
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
                SecretKey        securekey  = keyFactory.generateSecret(desKey);
                //Cipher对象实际完成加密操作
                Cipher cipher = Cipher.getInstance("DES");
                //用密匙初始化Cipher对象
                cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
                //现在,获取数据并加密
                //正式执行加密操作
                return cipher.doFinal(datasource);
            } catch (Throwable e) {
                e.printStackTrace();
            }
            return null;
        }
    
      /**
         * Base64编码
         *
         * @param input 要编码的字节数组
         * @return Base64编码后的字符串
         */
        public static String base64Encode2String(byte[] input) {
            return Base64.encodeToString(input, Base64.NO_WRAP);
        }
    
    

    相关文章

      网友评论

          本文标题:项目中接口传输的参数加密

          本文链接:https://www.haomeiwen.com/subject/tratgftx.html