石小疯 发表于 2024-9-20 09:26:49

加密与安全_解密AES加密中的IV和Seed

https://i-blog.csdnimg.cn/blog_migrate/89dc1208f809e9f7fdb170511b7862c9.png
概述

在AES加密中,**IV(Initialization Vector,初始化向量)和Seed(种子)**是两个差异的概念,尽管它们都涉及到随机性和加密安全性,但用途和作用有所差异。
IV(Initialization Vector,初始化向量)



[*]用途:IV 是在加密块模式(如 CBC, CFB, OFB, 等)中使用的一个随机或伪随机的输入值。它确保相同的明文在加密时产生差异的密文,从而增强了加密的安全性。
[*]特点:

[*]IV 通常是一个固定长度的随机数,长度与加密算法的块大小相同(比方,对于AES,IV长度为128位,即16字节)。
[*]在加密过程中,IV 通常与明文的第一个块举行某种形式的操作(如异或)来产生第一个加密块。后续块则依靠于前一个加密块。
[*]IV 不需要保密,但要确保每次加密都不相同,以防止模式分析攻击。

Seed(种子)



[*]用途:Seed 通常用于天生随机数或伪随机数。在加密算法中,随机数天生器需要一个初始值,Seed 用来设置这个初始状态,以便天生一系列的伪随机数。
[*]特点:

[*]Seed 可以是一个恣意长度的数值,用于初始化随机数天生器(如在密钥天生、随机添补、天生IV等场景中使用)。
[*]使用相同的 Seed 初始化同一个随机数天生器,将天生相同的伪随机数序列。因此,Seed 的选取应尽量多样化和随机化,以避免天生可预测的随机数序列。

Code

seed


import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.UUID;

/**
* AES 对称性加密
* <p>
* 需要依赖 Apache Commons Codec
*
* @author artisan
*/
public class AesUtil {

    /**
   * 加密算法类型
   */
    static final String ALGORITHM_KEY = "AES";

    /**
   * 算法长度
   */
    private static final int KEY_SIZE = 128;


    /**
   * 生成一个种子字符串
   * 该方法通过生成一个唯一标识符(UUID)来创建一个唯一的种子字符串
   * 使用UUID可以确保生成的种子在一定范围内具有唯一性
   *
   * @return 返回一个UUID作为种子字符串
   */
    public static String generateSeed() {
      return UUID.randomUUID().toString();
    }


    /**
   * 使用 种子(密码)、模式 创建密码加密
   *
   * @param seed 种子(密码)
   * @param mode 模式,加密:{@link Cipher#ENCRYPT_MODE},解密:{@link Cipher#DECRYPT_MODE}
   * @return 返回 密码加密
   * @throws NoSuchAlgorithmException 算法类型异常
   * @throws NoSuchPaddingException   算法填充异常
   * @throws InvalidKeyException      无效的密钥异常
   */
    public static Cipher cipher(String seed, int mode) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException {
      KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_KEY);
      byte[] seedBytes = seed.getBytes();
      keyGenerator.init(KEY_SIZE, new SecureRandom(seedBytes));
      SecretKey secretKey = keyGenerator.generateKey();
      byte[] encodedBytes = secretKey.getEncoded();
      SecretKeySpec secretKeySpec = new SecretKeySpec(encodedBytes, ALGORITHM_KEY);
      Cipher cipher = Cipher.getInstance(ALGORITHM_KEY);
      cipher.init(mode, secretKeySpec);
      return cipher;
    }

    /**
   * 使用 种子(密码)将内容 加密
   *
   * @param originalText 原文
   * @param seed         种子(密码)
   * @return 返回 加密结果
   * @throws NoSuchAlgorithmException算法类型异常
   * @throws NoSuchPaddingException    算法填充异常
   * @throws InvalidKeyException       无效的密钥异常
   * @throws BadPaddingException       错误填充异常
   * @throws IllegalBlockSizeException 非法的块大小异常
   */
    public static byte[] encrypt(byte[] originalText, String seed) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
      Cipher cipher = cipher(seed, Cipher.ENCRYPT_MODE);
      return cipher.doFinal(originalText);
    }

    /**
   * 使用 种子(密码)将内容 加密
   *
   * @param originalText 原文
   * @param seed         种子(密码)
   * @return 返回 加密结果
   * @throws NoSuchAlgorithmException算法类型异常
   * @throws NoSuchPaddingException    算法填充异常
   * @throws InvalidKeyException       无效的密钥异常
   * @throws BadPaddingException       错误填充异常
   * @throws IllegalBlockSizeException 非法的块大小异常
   */
    public static byte[] encrypt(String originalText, String seed) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
      return encrypt(originalText.getBytes(), seed);
    }

    /**
   * 使用 种子(密码)将内容 加密
   *
   * @param originalText 原文
   * @param seed         种子(密码)
   * @return 返回 加密结果
   * @throws NoSuchAlgorithmException算法类型异常
   * @throws NoSuchPaddingException    算法填充异常
   * @throws InvalidKeyException       无效的密钥异常
   * @throws BadPaddingException       错误填充异常
   * @throws IllegalBlockSizeException 非法的块大小异常
   */
    public static String encryptStr(String originalText, String seed) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
      byte[] encryptBytes = encrypt(originalText.getBytes(), seed);
      return Hex.encodeHexString(encryptBytes);
    }

    /**
   * 使用 种子(密码)将内容 解密
   *
   * @param cipherText 密文
   * @param seed       种子(密码)
   * @return 返回 解密原文
   * @throws NoSuchAlgorithmException算法类型异常
   * @throws NoSuchPaddingException    算法填充异常
   * @throws InvalidKeyException       无效的密钥异常
   * @throws BadPaddingException       错误填充异常
   * @throws IllegalBlockSizeException 非法的块大小异常
   */
    public static byte[] decrypt(byte[] cipherText, String seed) throws NoSuchAlgorithmException, BadPaddingException,
            IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException {
      Cipher cipher = cipher(seed, Cipher.DECRYPT_MODE);
      return cipher.doFinal(cipherText);
    }

    /**
   * 使用 种子(密码)将内容 解密
   *
   * @param cipherText 密文
   * @param seed       种子(密码)
   * @return 返回 解密原文
   * @throws NoSuchAlgorithmException算法类型异常
   * @throws NoSuchPaddingException    算法填充异常
   * @throws InvalidKeyException       无效的密钥异常
   * @throws BadPaddingException       错误填充异常
   * @throws IllegalBlockSizeException 非法的块大小异常
   * @throws DecoderException          解码器异常
   */
    public static byte[] decrypt(String cipherText, String seed) throws NoSuchAlgorithmException, BadPaddingException,
            IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException, DecoderException {
      byte[] contentBytes = Hex.decodeHex(cipherText);
      return decrypt(contentBytes, seed);
    }

    /**
   * 使用 种子(密码)将内容 解密
   *
   * @param cipherText 密文
   * @param seed       种子(密码)
   * @return 返回 解密原文
   * @throws NoSuchAlgorithmException算法类型异常
   * @throws NoSuchPaddingException    算法填充异常
   * @throws InvalidKeyException       无效的密钥异常
   * @throws BadPaddingException       错误填充异常
   * @throws IllegalBlockSizeException 非法的块大小异常
   * @throws DecoderException          解码器异常
   */
    public static String decryptStr(String cipherText, String seed) throws NoSuchAlgorithmException, BadPaddingException,
            IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException, DecoderException {
      byte[] decryptFrom = Hex.decodeHex(cipherText);
      byte[] decryptBytes = decrypt(decryptFrom, seed);
      return new String(decryptBytes);
    }

}

测试代码

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.junit.jupiter.api.Test;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
* AES 对称加密 测试类
*
* @author artisan
*/
public class AesUtils {

    /**
   * 生成一个种子字符串
   * 该方法通过生成一个唯一标识符(UUID)来创建一个唯一的种子字符串
   * 使用UUID可以确保生成的种子在一定范围内具有唯一性
   *
   * @return 返回一个UUID作为种子字符串
   */
    public static String generateSeed() {
      return UUID.randomUUID().toString();
    }

    /**
   * 字符串加密与解密
   */
    @Test
    public void string() throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException,
            NoSuchAlgorithmException, NoSuchPaddingException, DecoderException {

      String content = "21dsikhjihiuseiu23isdjahjsfhuahfuiashufsdajiafjihaseuihfwauisdloa'aops][sogjier";
      String seed =generateSeed();
      System.out.println(seed.length());
      System.out.println("原文:" + content);
      System.out.println("种子(密码):" + seed);

      String encryptStr = Aes.encryptStr(content, seed);
      System.out.println("加密结果:" + encryptStr);

      String decryptStr = Aes.decryptStr(encryptStr, seed);
      System.out.println("解密结果:" + decryptStr);
    }

    /**
   * 字节与字符串
   */
    @Test
    public void byteAndString() throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException,
            NoSuchAlgorithmException, NoSuchPaddingException, DecoderException {
      String content = "artisan go go go";
      String seed =generateSeed();

      System.out.println("原文:" + content);
      System.out.println("种子(密码):" + seed);

      byte[] encryptBytes = Aes.encrypt(content, seed);
      String encryptStr = Hex.encodeHexString(encryptBytes);
      System.out.println("加密结果:" + encryptStr);

      byte[] decryptBytes = Aes.decrypt(encryptStr, seed);
      System.out.println("解密结果:" + new String(decryptBytes));
    }

    /**
   * 字节
   */
    @Test
    public void bytes() throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException,
            NoSuchAlgorithmException, NoSuchPaddingException, DecoderException {
      String content = "aedksej sdksfdkhoweio (*&*^&^^^";
      String seed = generateSeed();

      System.out.println("原文:" + content);
      System.out.println("种子(密码):" + seed);

      byte[] encryptBytes = Aes.encrypt(content, seed);
      String encryptStr = Hex.encodeHexString(encryptBytes);
      System.out.println("加密结果:" + encryptStr);

      byte[] contentBytes = Hex.decodeHex(encryptStr);
      byte[] decryptBytes = Aes.decrypt(contentBytes, seed);
      System.out.println("解密结果:" + new String(decryptBytes));
    }

}

https://i-blog.csdnimg.cn/direct/d82245ef166e40dbb99e990de5e9c401.png
IV

package com.artisan.shuangxiang_aesrsa;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.util.Base64;

/**
* AES工具类,提供AES加密和解密功能
* 使用AES/CBC/PKCS5Padding算法进行加密和解密
*
* @author artisan
*/
public class AESUtil {
    /**
   * 定义加密算法类型为AES/CBC/PKCS5Padding
   */
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    /**
   * 使用AES算法加密数据
   *
   * @param data 待加密的字符串
   * @param key加密使用的SecretKey
   * @param iv   加密使用的初始化向量(IvParameterSpec)
   * @return 加密后的字符串,以Base64编码
   * @throws Exception 如果加密过程中发生错误,抛出异常
   */
    public static String encryptAES(String data, SecretKey key, IvParameterSpec iv) throws Exception {
      // 创建Cipher实例,指定使用AES/CBC/PKCS5Padding算法
      Cipher cipher = Cipher.getInstance(ALGORITHM);
      // 初始化Cipher为加密模式,传入密钥和初始化向量
      cipher.init(Cipher.ENCRYPT_MODE, key, iv);
      // 将待加密数据转换为字节数组,并执行加密操作
      byte[] encryptedData = cipher.doFinal(data.getBytes());
      // 将加密后的数据使用Base64编码,并返回
      return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
   * 使用AES算法解密数据
   *
   * @param encryptedData 待解密的字符串,以Base64编码
   * @param key         解密使用的SecretKey
   * @param iv            解密使用的初始化向量(IvParameterSpec)
   * @return 解密后的字符串
   * @throws Exception 如果解密过程中发生错误,抛出异常
   */
    public static String decryptAES(String encryptedData, SecretKey key, IvParameterSpec iv) throws Exception {
      // 创建Cipher实例,指定使用AES/CBC/PKCS5Padding算法
      Cipher cipher = Cipher.getInstance(ALGORITHM);
      // 初始化Cipher为解密模式,传入密钥和初始化向量
      cipher.init(Cipher.DECRYPT_MODE, key, iv);
      // 将待解密数据从Base64解码为字节数组
      byte[] decodedData = Base64.getDecoder().decode(encryptedData);
      // 执行解密操作
      byte[] decryptedData = cipher.doFinal(decodedData);
      // 将解密后的数据转换为字符串,并返回
      return new String(decryptedData);
    }
}
测试代码
package com.artisan.shuangxiang_aesrsa;

import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;

/**
* @author artisan
*/
public class Main_OnlyAES {


    /**
   * 使用RSA公钥加密AES密钥,以及使用RSA私钥解密AES密钥的全过程
   * 同时展示了使用AES密钥加密和解密数据的应用
   *
   * @param args 命令行参数
   * @throws Exception 可能抛出的异常
   */
    public static void main(String[] args) throws Exception {
      // 生成AES和RSA密钥
      SecretKey aesKey = KeyGeneration.generateAESKey();


      String aesKeyString = Base64.getEncoder().encodeToString(aesKey.getEncoded());
      System.out.println("AES密钥: " + aesKeyString);
      // 初始化IV(通常需要确保IV的安全传输)16字节的IV向量
      IvParameterSpec iv = new IvParameterSpec(new byte);


      // 使用AES加密和解密数据
      String originalData = "我是需要加密的数据artisan GO GO GO !!!";
      String encryptedData = AESUtil.encryptAES(originalData, aesKey, iv);
      System.out.println("加密的数据: " + encryptedData);

      String decryptedData = AESUtil.decryptAES(encryptedData, aesKey, iv);
      System.out.println("解密的数据: " + decryptedData);
    }
}


https://i-blog.csdnimg.cn/direct/7af237cc4b77428aa9eef87e62887446.png
小结



[*]IV 是加密过程的一部分,用于确保相同的明文在加密时能产生差异的密文,从而进步安全性。
[*]Seed 则是用于初始化随机数天生器,以天生伪随机数,这些伪随机数可以用于天生IV、密钥等。
固然IV有时可以通过随机数天生器来天生,这个随机数天生器可能使用Seed作为其输入,但它们的概念和用途是差异的。
https://i-blog.csdnimg.cn/direct/757d597253764906a7e2cb467d92173d.jpeg#pic_center

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 加密与安全_解密AES加密中的IV和Seed