栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java AES加密算法总结笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java AES加密算法总结笔记

加密算法
  • 对称加密算法
    • symmetric-key cryptography
    • 加密和解密使用相同密匙
    • 常用对称加密算法
      • DES
      • AES
  • 非对称加密算法
    • asymmetric-key cryptography
    • 加密和解密使用不同密匙
    • 常用非对称加密算法是RSA算法
AES加密
  • Advanced Encryption Standard 高级加密标准,是一种对称加密算法,取代了DES加密算法,因为AES安全性更高

  • https://zhuanlan.zhihu.com/p/396015712
    
  • APK解压文件


    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ofsRNsjj-1652588479816)(imgs/加密算法/image-20220514104440813.png)]
  • AES一些规则

    • AES是一种区块加密算法,加密时会将原始数据按大小拆分成一个个区块进行加密,区块大小固定为128比特(16字节)
    • AES密匙长度可以是128,192,256比特,密匙越长,安全性越高,而性能也就越低
  • AES工作模式

    • 多种工作模式
      • ECB,CBC,OFB,CFB等
      • 核心仍然是AES算法
  • AES填充方式

    • AES 是一种区块加密算法,加密时会将原始数据按大小拆分成一个个 128 比特(即 16 字节)区块进行加密,如果需要加密的原始数据不是 16 字节的整数倍时,就需要对原始数据进行填充,使其达到 16 字节的整数倍
    • 常用填充方式
      • PKCS5Padding、ISO10126Padding
  • Java中AES

    Java类

    • javax.crypto.Cipher
      
    • 加密与解密

    创建一个Cipher

    • Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      
    • 传递参数

      • algorithm/mode/padding 算法名/工作模式/填充方式
ECB
  • Electronic codebook

  • 将待加密数据拆分成块,并对每个块进行独立加密

  • public static byte[] encryptECB(byte[] data, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
        byte[] result = cipher.doFinal(data);
        return result;
    }
    
    public static byte[] decryptECB(byte[] data, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
        byte[] result = cipher.doFinal(data);
        return result;
    }
    
    public static void main(String[] args) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
        String data = "Hello World"; // 待加密的明文
        String key = "12345678abcdefgh"; // key 长度只能是 16、25 或 32 字节
    
        byte[] ciphertext = encryptECB(data.getBytes(), key.getBytes());
        System.out.println("ECB 模式加密结果(Base64):" + Base64.getEncoder().encodeToString(ciphertext));
    
        byte[] plaintext = decryptECB(ciphertext, key.getBytes());
        System.out.println("解密结果:" + new String(plaintext));
    }
    
  • ECB 模式有一个致命的缺点,由于该模式对每个块进行独立加密,会导致同样的明文块被加密成相同的密文块

CBC
  • Cipher-block chaining

  • 密码分组链接

  • 它的出现解决 ECB 同样的明文块会被加密成相同的密文块的问题

  • CBC 引入了初始向量的概念(IV,Initialization Vector),第一个明文块先与 IV 进行异或后再加密,后续每个明文块先与前一个密文块进行异或后再加密

  • public static byte[] encryptCBC(byte[] data, byte[] key, byte[] iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
        byte[] result = cipher.doFinal(data);
        return result;
    }
    
    public static byte[] decryptCBC(byte[] data, byte[] key, byte[] iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
        byte[] result = cipher.doFinal(data);
        return result;
    }
    
    public static void main(String[] args) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
        String data = "Hello World"; // 待加密的原文
        String key = "12345678abcdefgh"; // key 长度只能是 16、25 或 32 字节
        String iv = "iviviviviviviviv"; // CBC 模式需要用到初始向量参数
    
        byte[] ciphertext = encryptCBC(data.getBytes(), key.getBytes(), iv.getBytes());
        System.out.println("CBC 模式加密结果(Base64):" + Base64.getEncoder().encodeToString(ciphertext));
    
        byte[] plaintext = decryptCBC(ciphertext, key.getBytes(), iv.getBytes());
        System.out.println("解密结果:" + new String(plaintext));
    }
    
  • 由于 CBC 每个明文块加密都依赖前一个块的加密结果,所以其主要缺点在于加密过程是串行的,无法被并行化

GCM
  • Galois/Counter Mode

  • 不但提供了加密解密,还提供了数据完整性校验,防止篡改

  • AES-GCM 模式是目前使用最广泛的模式

  • 需要以下参数

    • 待加密的明文
    • 密钥
    • 初始向量 IV
    • additional authenticated data (AAD)
  • public static byte[] encryptGCM(byte[] data, byte[] key, byte[] iv, byte[] aad) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(128, iv));
        cipher.updateAAD(aad);
        byte[] result = cipher.doFinal(data);
        return result;
    }
    
    public static byte[] decryptGCM(byte[] data, byte[] key, byte[] iv, byte[] aad) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(128, iv));
        cipher.updateAAD(aad);
        byte[] result = cipher.doFinal(data);
        return result;
    }
    
    public static void main(String[] args) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
        String data = "Hello World"; // 待加密的原文
        String key = "12345678abcdefgh"; // key 长度只能是 16、25 或 32 字节
        String iv = "iviviviviviviviv";
        String aad = "aad"; // AAD 长度无限制,可为空
    
        byte[] ciphertext = encryptGCM(data.getBytes(), key.getBytes(), iv.getBytes(), aad.getBytes());
        System.out.println("GCM 模式加密结果(Base64):" + Base64.getEncoder().encodeToString(ciphertext));
    
        byte[] plaintext = decryptGCM(ciphertext, key.getBytes(), iv.getBytes(), aad.getBytes());
        System.out.println("解密结果:" + new String(plaintext));
    }
    
    • 是流加密(Stream cipher)算法,所以对应的填充模式为 NoPadding
获取钥匙与IV
  • String 密码 获取 secretKeySpec

    • private static SecretKey getKey(String password) {
              int keyLength = 128;  // 密匙bit长度
              byte[] keyBytes = new byte[keyLength / 8];
              SecretKeySpec key = null;
              try {
                  Arrays.fill(keyBytes, (byte) 0x0);
                  byte[] passwordBytes = password.getBytes("UTF-8");
                  int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length;
                  System.arraycopy(passwordBytes, 0, keyBytes, 0, length); // copy数组
                  key = new SecretKeySpec(keyBytes, "AES");
              } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
              }
              return key;
          }
      
  • 获取IV

    • new IvParameterSpec(iv.getBytes())		// CBC模式
      new GCMParameterSpec(128, iv.getBytes())  // GCM模式
      
遇到问题
  • 文件加密后,从文件读取流出现解密错误
    • 面对文件流应该使用CipherInputStream 和 CipherOutputStream
    • 见java包
  • ADD是身份认证,GCM模式下可以选择添加
    • Additianal Authenticated Data

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/889066.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号