zoukankan      html  css  js  c++  java
  • Java 关于密码处理的工具类[MD5编码][AES加密/解密]

    项目中又遇到了加密问题,又去翻了半天,然后做测试,干脆就把常用的两类小结一下.

    1.第一种所谓的MD5加密

     其实也不算加密,只是基于Hash算法的不可逆编码而已,等于说,一旦经过MD5处理,是不可能从编码后的字符串反推回去的.

     MD5的方法是基于散列的。本身信息不全。理论上是不能还原成唯一字符串的。

     网上所谓的解密,也只是拥有一个足够大的字典映射,将编码前的源字符和编码后的目标字符关联起来而已,大多数常见的还行,复杂点的估计就会话费很长时间,有兴趣的可以试试.

     

     至于MD5的用法,在初次录入的时候,也就做一次编码,而后存储,没什么可说的.主要是验证一致性,如登录中的密码,普遍做法就是将新获取的密码编码,在用编码之后的和数据库中的比较,判断是否一致.

     理论上来讲,对于这个密码,除了使用的人,其他人是不知道的,包括管理员.

     一般的系统这种方案也就够用了.或者利用MD5多次编码(加密),次数自己控制即可,也能增加点安全性.

    2.第二种就是AES加密/解密

     AES 是一种对称加密算法,加密过程中要使用密钥这个东西. 有兴趣的可以去仔细了解一下: http://www.mamicode.com/info-detail-514466.html

     就是说,我有个密码:mima001,要使用AES加密,此时我就需要提供一个 密钥(key) :thisKey,然后使用AES算法加密,得到一个结果result,存入数据库;

     然后,解密的时候,我们从数据库中拿到这个result,然后同时也要获得上面加密的时候用到的密钥:thisKey,然后使用AES算法解密;

     在这个过程中,如果有密钥,则整个过程是可逆的,并且密钥只有一个,可逆相对来说也就是对称的,加密前和解密后的东西,没有什么差异.

    另外,补充一点啊,就是加密解密基础问题:字节数组和(16进制)字符串的相互转换

    在加密时,一般加密算法和hash算法,它们操作的都是字节数组,对字节数组按照加密算法进行各种变换,运算,得到的结果也是字节数组。而我们一般是要求对字符串进行加密,所以就涉及到字符串String到 byte[] 的转换,这个很简单。同时在解密时,也涉及到字节数组byte[] 到 String 的转换。另外在对用户的密码进行hash加密之后,最终是要保存在数据库中,所以加密得到 byte[] 也要转换到 String.

    想了解详细一点的朋友可以去: http://www.cnblogs.com/digdeep/p/4627813.html 看看.

    下面是工具类:提供了加密方法,解密方法,还有讲加密结果转换为常见的字符串转换方法.

      1 import javax.crypto.*;
      2 import javax.crypto.spec.SecretKeySpec;
      3 import java.io.UnsupportedEncodingException;
      4 import java.security.InvalidKeyException;
      5 import java.security.MessageDigest;
      6 import java.security.NoSuchAlgorithmException;
      7 import java.security.SecureRandom;
      8 
      9 /**
     10  * @see: PasswordUtil
     11  * @author: lnexin@aliyun.com
     12  * @date: 2017-04-29  10:12
     13  */
     14 public class PasswordUtil {
     15     /**
     16      * 使用:
     17      *      直接使用即可,至于具体参数,看下面方法的说明即可;
     18      *      1. PasswordUtil.MD5Encode();  MD5不可逆简单加密:散列函数-基于HASH算法的编码
     19      *      2. PasswordUtil.AESEncrypt(); AES加密
     20      *      3. PasswordUtil.AESDecrypt(); AES解密
     21      *      4. PasswordUtil.parseByte2HexStr(); 二进制到16进制
     22      *      5. PasswordUtil.parseHexStr2Byte(); 16进制到2进制
     23      */
     24     
     25     // 16进制的字符数组
     26     private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
     27     
     28     /**
     29      * @param source    原字符串
     30      * @param encoding  指定编码类型
     31      * @param uppercase 是否转为大写字符串
     32      */
     33     public static String MD5Encode(String source, String encoding, boolean uppercase) {
     34         String result = null;
     35         try {
     36             result = source;
     37             // 获得MD5摘要对象
     38             MessageDigest messageDigest = MessageDigest.getInstance("MD5");
     39             // 使用指定的字节数组更新摘要信息
     40             messageDigest.update(result.getBytes(encoding));
     41             // messageDigest.digest()获得16位长度
     42             // result = parseByte2HexStr(messageDigest.digest());
     43             result = byteArrayToHexString(messageDigest.digest());
     44             
     45         } catch (Exception e) {
     46             e.printStackTrace();
     47         }
     48         return uppercase ? result.toUpperCase() : result;
     49     }
     50     
     51     /**
     52      * AES 加密
     53      *
     54      * @param content 需要加密的内容
     55      * @param aesKey  加密密钥
     56      * @return
     57      */
     58     public static byte[] AESEncrypt(String content, String aesKey) {
     59         try {
     60             KeyGenerator kgen = KeyGenerator.getInstance("AES");
     61             kgen.init(128, new SecureRandom(aesKey.getBytes()));
     62             SecretKey secretKey = kgen.generateKey();
     63             byte[] enCodeFormat = secretKey.getEncoded();
     64             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
     65             Cipher cipher = Cipher.getInstance("AES");// 创建密码器
     66             byte[] byteContent = content.getBytes("utf-8");
     67             cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
     68             byte[] result = cipher.doFinal(byteContent);
     69             return result; // 加密
     70         } catch (NoSuchAlgorithmException e) {
     71             e.printStackTrace();
     72         } catch (NoSuchPaddingException e) {
     73             e.printStackTrace();
     74         } catch (InvalidKeyException e) {
     75             e.printStackTrace();
     76         } catch (UnsupportedEncodingException e) {
     77             e.printStackTrace();
     78         } catch (IllegalBlockSizeException e) {
     79             e.printStackTrace();
     80         } catch (BadPaddingException e) {
     81             e.printStackTrace();
     82         }
     83         return null;
     84     }
     85     
     86     /**
     87      * 解密
     88      *
     89      * @param content 待解密内容
     90      * @param aesKey  解密密钥 秘miyao
     91      * @return
     92      */
     93     public static byte[] AESDecrypt(byte[] content, String aesKey) {
     94         try {
     95             KeyGenerator kgen = KeyGenerator.getInstance("AES");
     96             kgen.init(128, new SecureRandom(aesKey.getBytes()));
     97             SecretKey secretKey = kgen.generateKey();
     98             byte[] enCodeFormat = secretKey.getEncoded();
     99             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
    100             Cipher cipher = Cipher.getInstance("AES");// 创建密码器
    101             cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
    102             byte[] result = cipher.doFinal(content);
    103             return result; // 加密
    104         } catch (NoSuchAlgorithmException e) {
    105             e.printStackTrace();
    106         } catch (NoSuchPaddingException e) {
    107             e.printStackTrace();
    108         } catch (InvalidKeyException e) {
    109             e.printStackTrace();
    110         } catch (IllegalBlockSizeException e) {
    111             e.printStackTrace();
    112         } catch (BadPaddingException e) {
    113             e.printStackTrace();
    114         }
    115         return null;
    116     }
    117     
    118     /**
    119      * 将二进制转换成16进制
    120      */
    121     public static String parseByte2HexStr(byte buf[]) {
    122         StringBuffer sb = new StringBuffer();
    123         for (int i = 0; i < buf.length; i++) {
    124             String hex = Integer.toHexString(buf[i] & 0xFF);
    125             if (hex.length() == 1) {
    126                 hex = '0' + hex;
    127             }
    128             sb.append(hex.toUpperCase());
    129         }
    130         return sb.toString();
    131     }
    132     
    133     /**
    134      * 将16进制转换为二进制
    135      */
    136     public static byte[] parseHexStr2Byte(String hexStr) {
    137         if (hexStr.length() < 1)
    138             return null;
    139         byte[] result = new byte[hexStr.length() / 2];
    140         for (int i = 0; i < hexStr.length() / 2; i++) {
    141             int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
    142             int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
    143             result[i] = (byte) (high * 16 + low);
    144         }
    145         return result;
    146     }
    147     
         //byte转16进制 148 private static String byteArrayToHexString(byte[] bytes) { 149 StringBuilder stringBuilder = new StringBuilder(); 150 for (byte tem : bytes) { 151 stringBuilder.append(byteToHexString(tem)); 152 } 153 return stringBuilder.toString(); 154 } 155 //16进制转byte[] 156 private static String byteToHexString(byte b) { 157 int n = b; 158 if (n < 0) { 159 n = 256 + n; 160 } 161 int d1 = n / 16; 162 int d2 = n % 16; 163 return hexDigits[d1] + hexDigits[d2]; 164 } 165 166 }

    使用说明:

    随便写个测试类:截图直观一点,控制台输出在图右下角,测试具体代码在文末.

     1 public class PasswordTest {
     2     
     3     
     4     @Test
     5     public void MD5Test() throws Exception {
     6         String encode = PasswordUtil.MD5Encode("admin", "UTF8", true);
     7         System.out.println();
     8         System.out.println("MD5算法:"+encode);
     9     }
    10     
    11     @Test
    12     public void aesTest() throws Exception {
    13         String content = "admin";
    14         String aesKey = "thisiskey";
    15         
    16         byte[] encrypt = PasswordUtil.AESEncrypt(content, aesKey);//加密
    17         System.out.println("AES加密后-byte[]:"+encrypt);
    18         
    19         String strHex = PasswordUtil.parseByte2HexStr(encrypt);
    20         System.out.println("转换后的十六进制:"+strHex);
    21         
    22         
    23         byte[] decrypt = PasswordUtil.AESDecrypt(PasswordUtil.parseHexStr2Byte(strHex), aesKey);//解密
    24         System.out.println("AES解密后-byte[]"+decrypt);
    25         System.out.println("AES解密转换后:"+new String(decrypt));
    26     }
    27     
    28 }

    使用工具类的时候,要传入什么参数,主要方法上面的注释即可;

  • 相关阅读:
    BZOJ2870 最长道路
    BZOJ1316 树上的询问
    BZOJ2238 Mst
    BZOJ4242 水壶
    [BeiJing2010组队]次小生成树Tree
    CODEVS1403 新三国争霸
    牛客网NOIP赛前集训营-提高组(第六场) C-树
    JSOI2008 最小生成树计数
    BZOJ2654 Tree
    牛客网NOIP赛前集训营-提高组(第六场)B-选择题
  • 原文地址:https://www.cnblogs.com/applerosa/p/6785486.html
Copyright © 2011-2022 走看看