AES代码演示

AES 分组核心原理参考:

https://www.jianshu.com/p/0c603e1c2fa7

package com.deepway.cryptology;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Arrays;

/**
 * AES 工作模式 演示
 * <p>
 * AES默认加密模式 就是ECB
 * 参考:https://blog.csdn.net/qq_41035588/article/details/121666788
 *
 * @author huyanbing
 * @create 2022/12/17 4:01 下午
 */
public class AESModeTest extends BaseCipher {
    private static final String ALGO = "AES";

    private static final int IV_SIZE = 16;


    //持有iv 不共享不更新
    private byte[] iv;
    //前一次计算状态的保持
    private byte[] prevState;

    private Cipher aes;

    public AESModeTest(int keyLen, byte[] plainKey) {

        super(keyLen, plainKey);
    }


    private void initialize() throws GeneralSecurityException {

        //生成 iv
        iv = generateIV();
        //iv as prevState
        //拷贝一份 prevState   这个 prevState 是要读写改变的
        prevState = Arrays.copyOf(iv, iv.length);

        //拿密码器
        aes = Cipher.getInstance(ALGO);
        aes.init(Cipher.ENCRYPT_MODE, key);


    }


    private byte[] generateIV() {
        //填充
        byte[] iv = new byte[IV_SIZE];
        //随机生成  这里必须使用安全的随机数生成器  SecureRandom  不能使用其他的随机数生成器
        new SecureRandom().nextBytes(iv);
        return iv;
    }

    private void resetDecryptPrevState() {
        try {
            aes.init(Cipher.DECRYPT_MODE, key);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        //拷贝一份 prevState   这个 prevState 是要读写改变的
        prevState = Arrays.copyOf(iv, iv.length);
    }


    /**
     * ECB 模式加密
     *
     * @param plainText
     * @return
     */
    public byte[] encrypt_ECB(byte[] plainText) throws IllegalBlockSizeException, BadPaddingException {

        // aes.update(plainText);
        return aes.doFinal(plainText);
    }


    /**
     * ECB 模式解密
     *
     * @param cipherText
     * @return
     */
    public byte[] decrypt_ECB(byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
        aes.init(Cipher.DECRYPT_MODE, key);
        //aes.update(cipherText);
        return aes.doFinal(cipherText);
    }

    /***
     * CBC 模式的逻辑演示
     * prevCipherText=iv<==At first
     * @param plainText
     * @return
     */
    public byte[] encrypt_CBC(byte[] plainText) throws IllegalBlockSizeException, BadPaddingException {

        assert plainText.length == 128 >> 3;

        byte[] x = new byte[16];
        for (int i = 0; i < x.length; i++) {
            //CBC模式 需要明文与上一轮结果做异或,然后再输入到加密算法中
            //x 为异或结果   prevState 初始值是 IV
            x[i] = (byte) (plainText[i] ^ prevState[i]);
        }
        //返回加密结果
        // prevState = aes.update(x);
        return prevState = aes.doFinal(x);
    }

    /**
     * CBC 解密方法  解密方法 相当于加密方法的反向
     *
     * @param cipherText
     * @return
     */
    public byte[] decrypt_CBC(byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException {

        resetDecryptPrevState();
        assert cipherText.length == 128 >> 3;

        //加密 aes.update 是最后一步,解密 aes.update是第一步
        // byte[] x = aes.update(cipherText);
        byte[] x = aes.doFinal(cipherText);
        for (int i = 0; i < x.length; i++) {
            //x[] 刚开始并不是明文 还是密文,经过和prevState[i] 异或之后 写回 x[]
            x[i] ^= prevState[i];
        }
        //同时要把当前密文数据 更新给 prevState
        prevState = cipherText;
        return x;
    }


    /**
     * CFB 模式的逻辑演示
     * prevCipherText=iv<==At first
     *
     * @param plainText
     * @return
     */
    private byte[] encrypt_CFB(byte[] plainText) throws IllegalBlockSizeException, BadPaddingException {

        assert plainText.length == 128 >> 3;

        byte[] y = aes.update(prevState);
        //byte[] y = aes.doFinal(prevState);
        for (int i = 0; i < y.length; i++) {
            //CFB模式是用加密完的结果去异或明文
            y[i] ^= plainText[i];
        }

        //并且它加密的不是明文数据,而是 IV
        //然后加密之后 生成 y ,y 与明文异或 写回y[i]
        //让后将prevState=y
        return prevState = y;
    }


    /**
     * CFB 解密
     *
     * @param cipherText
     * @return
     */
    public byte[] decrypt_CFB(byte[] cipherText) throws IllegalBlockSizeException, BadPaddingException {

        resetDecryptPrevState();
        assert cipherText.length == 128 >> 3;

        //解密也是调用的加密方法
        byte[] x = aes.update(prevState);
        //byte[] x = aes.doFinal(prevState);
        for (int i = 0; i < x.length; i++) {
            //密文异或 并写回原文消息
            x[i] ^= cipherText[i];
        }
        //并用当前密文消息 更新 prevState 当前状态
        prevState = cipherText;
        return x;
    }

    /**
     * OFB 模式的逻辑演示
     * prevCipherText=iv<==At frist
     *
     * @param plainText
     * @return
     */
    public byte[] encrypt_OFB(byte[] plainText) {

        assert plainText.length == 128 >> 3;

        byte[] y = aes.update(prevState);
        // 和 CFB 区别 重点  块加密的的运算结果,需要保留下来到prevState
        prevState = Arrays.copyOf(y, y.length);
        for (int i = 0; i < y.length; i++) {
            //和CFB比较类似
            y[i] ^= plainText[i];
        }

        //CFB 是  在这
        return y;
    }


    /**
     * OFB  解密  与加密模式是一样的
     *
     * @param cipherText
     * @return
     */
    public byte[] decrypt_OFB(byte[] cipherText) {
        return encrypt_OFB(cipherText);
    }


    /**
     * CTR模式  加密
     * prevCipherText =iv <==At frist
     *
     * @param plainText
     * @return
     */
    public byte[] encrypt_CTR(byte[] plainText) {
        assert plainText.length == 128 >> 3;

        byte[] x = aes.update(prevState);
        for (int i = 0; i < x.length; i++) {
            //异或明文 就可以得到加密x了
            x[i] ^= plainText[i];
        }

        // increment :counter++
        for (int i = 15; i >= 0; --i) {

            //因为prevState是一个很大的数字,所以从地位到高位不断自增的一个小小的算法过程
            //如果自增不为零 ++prevState[i]!=0  那么 i-- 向前一位
            if (++prevState[i] != 0) {
                break;
            }
        }

        return x;
    }

    /**
     * CTR模式  解密
     * prevCipherText =iv <==At frist
     * 解密操作和加密操作一样
     *
     * @param cipherText
     * @return
     */
    public byte[] decrypt_CTR(byte[] cipherText) {
        return encrypt_CTR(cipherText);
    }


    public static void main(String[] args) throws GeneralSecurityException {


        AESModeTest test = new AESModeTest(128, "0123456789012345".getBytes());


        //打印当前的 key
        String hex = HexCustomUtil.bytes2hex(test.key.getEncoded());

        System.out.println("---------key----------------");
        System.out.println(hex);


        //明文 PlainText
        byte[] plainText = "8888888888888888".getBytes();

        //打印明文
        System.out.println("---------明文----------------");
        System.out.println(HexCustomUtil.bytes2hex(plainText));
        System.out.println(new String(plainText));

        //加密
        test.initialize();
        byte[] cipherText = test.encrypt_CBC(plainText);

        //打印密文
        System.out.println("---------密文----------------");
        System.out.println(HexCustomUtil.bytes2hex(cipherText));
        // System.out.println(new String(cipherText));


        //解密
        byte[] decryptArr = test.decrypt_CBC(cipherText);

        System.out.println("---------解密后明文----------------");
        System.out.println(HexCustomUtil.bytes2hex(decryptArr));
        System.out.println(new String(decryptArr));
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值