java实现AES对称加密的demo

java实现AES对称加密demo

最近公司需要学习到数据传输的加密,我也看了对称加密的文档,所谓的对称加密就是说加密和解密共用一套密钥,于是我选用了常用的AES对称加密,下图是一个基本原理。
3333

  • 首先需要生成密钥,在SecureRandom.getInstance()方法里面需要加入参数"SHA1PRNG",不然在linux系统上解密失败报错Given final block not properly padded. Such issues can arise if a bad key is used during decryption.,具体原因不知;下面加密设置了种子,这样每次生成的密钥都会是相同的,也可以去掉,这样生成的密钥就会有所不同。

    private SecretKey geneKey() throws Exception {
            //获取一个密钥生成器实例
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed("123456".getBytes());//设置加密用的种子,密钥
            keyGenerator.init(random);
            SecretKey secretKey = keyGenerator.generateKey();
            //把上面的密钥存起来
            Path keyPath = Paths.get("D://aes.key");
            Files.write(keyPath, secretKey.getEncoded());
            return secretKey;
    }
    
    
    
  • 然后用生成的密钥对所需要的数据进行加密,这里还对加密后的内容进行了base64编码,反之解密的时候也需要先base64解码

    public String encrypt(String encryptStr) throws Exception {
            //1、指定算法、获取Cipher对象
            Cipher cipher = Cipher.getInstance(ALGORITHM);//算法是AES
            //2、生成/读取用于加解密的密钥
            SecretKey secretKey = this.geneKey();
            //3、用指定的密钥初始化Cipher对象,指定是加密模式,还是解密模式
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            //4、更新需要加密的内容
            cipher.update(encryptStr.getBytes());
            //5、进行最终的加解密操作
            byte[] result = cipher.doFinal();//加密后的字节数组
            //也可以把4、5步组合到一起,但是如果保留了4步,同时又是如下这样使用的话,加密的内容将是之前update传递的内容和doFinal传递的内容的和。
    //      byte[] result = cipher.doFinal(content.getBytes());
            String base64Result = Base64.getEncoder().encodeToString(result);//对加密后的字节数组进行Base64编码
            return base64Result;
     }
    
  • 解密

    public String decrpyt(String desrpytStr) throws Exception {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            SecretKey secretKey = this.geneKey();
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] encodedBytes = Base64.getDecoder().decode(desrpytStr.getBytes());
            byte[] result = cipher.doFinal(encodedBytes);//对加密后的字节数组进行解密
            return new String(result);
     }
    

    也可以根据路径去读取密钥,如下(推荐,这样就不用重新生成密钥)

    private SecretKey readKey(Path keyPath) throws Exception {
            //读取存起来的密钥
            byte[] keyBytes = Files.readAllBytes(keyPath);
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, ALGORITHM);
            return keySpec;
     }
     
     public String decrpyt(String desrpytStr) throws Exception {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            Path keyPath = Paths.get(keyUrl);
            SecretKey secretKey = this.readKey(keyPath);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] encodedBytes = Base64.getDecoder().decode(desrpytStr.getBytes());
            byte[] result = cipher.doFinal(encodedBytes);//对加密后的字节数组进行解密
            return new String(result);
     }
    
  • 最后给出全部代码

    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.security.SecureRandom;
    import java.util.Base64;
    
    public class AESUtil {
        private static final String ALGORITHM = "AES";
    
        //密钥的存放位置
        private String keyUrl = "D:/aes.key";
    
        /**
         * 生成密钥
         * @return
         * @throws Exception
         */
        private SecretKey geneKey() throws Exception {
            //获取一个密钥生成器实例
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed("123456".getBytes());//设置加密用的种子,密钥,这个可不操作,固定了的话每次出来的密钥时一样的
            keyGenerator.init(random);
            SecretKey secretKey = keyGenerator.generateKey();
            //把上面的密钥存起来
            Path keyPath = Paths.get(keyUrl);
            Files.write(keyPath, secretKey.getEncoded());
            return secretKey;
        }
    
    
        /**
         * 读取存储的密钥
         * @param keyPath
         * @return
         * @throws Exception
         */
        private SecretKey readKey(Path keyPath) throws Exception {
            //读取存起来的密钥
            byte[] keyBytes = Files.readAllBytes(keyPath);
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, ALGORITHM);
            return keySpec;
        }
    
        /**
         * 加密
         */
        public String encrypt(String encryptStr) throws Exception {
            //1、指定算法、获取Cipher对象
            Cipher cipher = Cipher.getInstance(ALGORITHM);//算法是AES
            //2、生成/读取用于加解密的密钥
            SecretKey secretKey = this.geneKey();
            //3、用指定的密钥初始化Cipher对象,指定是加密模式,还是解密模式
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            //4、更新需要加密的内容
            cipher.update(encryptStr.getBytes());
            //5、进行最终的加解密操作
            byte[] result = cipher.doFinal();//加密后的字节数组
            //也可以把4、5步组合到一起,但是如果保留了4步,同时又是如下这样使用的话,加密的内容将是之前update传递的内容和doFinal传递的内容的和。
    //      byte[] result = cipher.doFinal(content.getBytes());
            String base64Result = Base64.getEncoder().encodeToString(result);//对加密后的字节数组进行Base64编码
            return base64Result;
        }
    
        /**
         * 解密
         */
        public String decrpyt(String desrpytStr) throws Exception {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            Path keyPath = Paths.get(keyUrl);
            SecretKey secretKey = this.readKey(keyPath);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] encodedBytes = Base64.getDecoder().decode(desrpytStr.getBytes());
            byte[] result = cipher.doFinal(encodedBytes);//对加密后的字节数组进行解密
            return new String(result);
        }
        
        
        public static void main(String[] args) throws Exception {
            AESUtil aesUtil = new AESUtil();
            String enctyptStr = aesUtil.encrypt("123456aaa");
            System.err.println(enctyptStr);
            String decrpytStr = aesUtil.decrpyt(enctyptStr);
            System.err.println(decrpytStr);
        }
    }
    

ccc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值