zoukankan      html  css  js  c++  java
  • AES加密解密工具类封装(AESUtil)

    
    
    package club.codeapes.common.utils;

    import org.springframework.util.Base64Utils;

    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    /**
    * @version V1.0
    * @desc AES 加密工具类
    */
    public class AESUtil {

    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法
    //自定义密码
    private static final String ASSETS_DEV_PWD_FIELD = "xxxx";

    public static String getAssetsDevPwdField() {
    return ASSETS_DEV_PWD_FIELD;
    }

    /**
    * AES 加密操作
    *
    * @param content 待加密内容
    * @param password 加密密码
    * @return 返回Base64转码后的加密数据
    */
    public static String encrypt(String content, String password) {
    try {
    Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器

    byte[] byteContent = content.getBytes("utf-8");

    cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器

    byte[] result = cipher.doFinal(byteContent);// 加密

    return Base64Utils.encodeToString(result);//通过Base64转码返回
    } catch (Exception ex) {
    Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
    }

    return null;
    }

    /**
    * AES 解密操作
    *
    * @param content
    * @param password
    * @return
    */
    public static String decrypt(String content, String password) {

    try {
    //实例化
    Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

    //使用密钥初始化,设置为解密模式
    cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));

    //执行操作
    byte[] result = cipher.doFinal(Base64Utils.decodeFromString(content));
    String s = new String(result, "utf-8");
    return s;
    } catch (Exception ex) {
    ex.printStackTrace();
    Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
    }

    return null;
    }

    /**
    * 生成加密秘钥
    *
    * @return
    */
    private static SecretKeySpec getSecretKey(String password) {
    //返回生成指定算法密钥生成器的 KeyGenerator 对象
    KeyGenerator kg = null;
    try {
    kg = KeyGenerator.getInstance(KEY_ALGORITHM);
    SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
    random.setSeed(password.getBytes());
    //AES 要求密钥长度为 128
    kg.init(128, random);
    //生成一个密钥
    SecretKey secretKey = kg.generateKey();
    return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
    } catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
    }

    public static void main(String[] args) {
    String origin = "my test string";
    String encrypt = AESUtil.encrypt(origin, AESUtil.ASSETS_DEV_PWD_FIELD);
    String decrypt = AESUtil.decrypt(encrypt, AESUtil.ASSETS_DEV_PWD_FIELD);
    System.out.println(origin);
    System.out.println(encrypt);
    System.out.println(decrypt);
    }

    }
     

    关于过程中,为什么可以用base64对产生的数组进行编码,以及解码。使用的时候可能产生异常:解密的字节数组必须是16的倍数

    发现当把字节数组转为字符串后,在把字符串.getBytes()获得数组,发现两个字节数组前后不一样了

    强调一下:new String(byte[]),和"str".getBytes(),两个方法使用的编码一样,然后换成其他编码也出现这样情况

    原因:

    1. 为什么数组转字符串,字符串然后转数组会出现,前后两个字节数组的值会不同,因为并不是每个字节数和编码集上的字符都有对应关系,如果一个字节数在编码集上没有对应,编码new String(byte[]) 后,往往解出来的会是一些乱码无意义的符号:例如:��,

    但是解码的时候,�这个字符也是一个字符在编码表中也有固定的字节数用来表示,所有解码出来的值必定是编码表中对应的值,除非你的字节数组中的字节数正好在编码表中有对应的值,否则编码,解码后的字节数组会不一样

    误区: 误以为所有的字节数组都可以new String(),然后在通过String.getBytes()还原

    2.再说这个异常报:解密的字节数组必须是16的倍数,这得从AES的原理说起,AES是把数据按16字节分组加密的,所有如果数组长度不是16的倍数会报错

    AES原理:AES是对数据按128位,也就是16个字节进行分组进行加密的,每次对一组数据加密需要运行多轮。而输入密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节,如果用户输入的密钥长度不是这几种长度,也会补成这几种长度。无论输入密钥是多少字节,加密还是以16字节的数据一组来进行的,密钥长度的不同仅仅影响加密运行的轮数。

     可以用base64对参生的数组进行编码,然后在解码,这样不会像new String(byte[]),getBytes()那样造成数组前后不一致,一开始,我看到大部分人都是用base64,我也只是以为多一层编码看起来安全一些而已,没想到base64对数组的处理是不会造成误差的

     
  • 相关阅读:
    jQuery UI炫酷雨滴落在水面上的波纹涟漪特效
    mysql_jdbc
    数据库设计---合适的就是最好的
    谈谈 .NET Reflector
    整型反序
    iOS给Model排序
    php安装zendDebug
    zTree实现地市县三级级联封装类
    rnnlm源代码分析(八)
    CSS制作响应式正方形及其应用
  • 原文地址:https://www.cnblogs.com/chenmz1995/p/11548598.html
Copyright © 2011-2022 走看看