zoukankan      html  css  js  c++  java
  • java实现AES加解密

    近些年DES使用越来越少,原因就在于其使用56位密钥,比较容易被破解,近些年来逐渐被AES替代,AES已经变成目前对称加密中最流行算法之一;
    AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。本文就简单介绍如何通过JAVA实现AES加密。

    /**
    * AES加密字符串
    * @param content 需要被加密的字符串
    * @param password 加密需要的密码
    * @return 密文
    */
    public static String aesEncrypt(String content, byte [] password) {
    try {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者

    kgen.init(128, new SecureRandom(password));// 利用用户密码作为随机数初始化出
    // 128位的key生产者
    //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行

    SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥

    byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回// null。

    SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥

    Cipher cipher = Cipher.getInstance("AES");// 创建密码器

    byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);

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

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

    return Base64.getEncoder().encodeToString(result);//返回字节数据用Base64编码,解密之前先用Base64解码

    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    注意:加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;要避免这种情况,可以考虑将二进制数据转换成十六进制表示或者用Base64编码成字符串表示;

    /**
    * 解密AES加密过的字符串
    * @param content AES加密过过的内容
    * @param password 加密时的密码
    * @return 明文
    */
    public static String aesDecrypt(String content, byte [] password) {
    try {
    //base64解码
    byte [] message = Base64.getDecoder().decode(content);
    KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
    kgen.init(128, new SecureRandom(password));
    SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
    byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
    SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
    Cipher cipher = Cipher.getInstance("AES");// 创建密码器
    cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
    byte[] result = cipher.doFinal(message);
    return new String(result,StandardCharsets.UTF_8); // 明文

    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }


    另外一种加密方式

    /**
    * 加密
    * @param content 需要加密的内容, 待加密内容的长度必须是16的倍数
    * @param password 加密密码, 密钥必须是16位的
    * @return
    */
    public static byte[] encrypt2(String content, String password) {
      try {
        SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        byte[] byteContent = content.getBytes("utf-8");
        cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
        byte[] result = cipher.doFinal(byteContent);
        return result; // 加密
       } catch (Exception e) {
        e.printStackTrace();
       }
        return null;
    }

    这种加密方式有两种限制:
    1.密钥必须是16位的
    2.待加密内容的长度必须是16的倍数,如果不是16的倍数,就会出如下异常:
    javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
            at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
            at javax.crypto.Cipher.doFinal(DashoA13*..)
    要解决如上异常,可以通过补全传入加密内容等方式进行避免。

  • 相关阅读:
    java的访问控制修饰符
    js将一个数组分割成二维子数组
    java的数组
    Java 变量类型
    java
    java的 %和 ^
    Python第三方库 -> 由于是ipynb格式,所以没有对应的输出结果
    获取浏览器历史记录 browserhistory
    虚拟机 CentOS 6.8 安装
    解决 django.db.utils.OperationalError: (1051, "Unknown table 'mydorm.users_studen t'")
  • 原文地址:https://www.cnblogs.com/maxiw/p/12397782.html
Copyright © 2011-2022 走看看