JAVA 简单实现AES加密

昨天有个功能,跟其他系统对接,所以研究了下AES加密,综合的几个博客,新建了个demo。
效果预览,原理什么的就不解释了(因为我也不大懂(-_ - *),看着好像都差不多,凑合方法整成能用就行)
效果预览
好处是不用外部jar包
在这里插入图片描述
新建个随便整个springboot工程,搞个手写个工具类

package com.encryption.demo;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Arrays;

/**
 * @Description AES加密工具类
 * @Author 古大帅哥
 * @Date 2020/5/20 14:19
 */
public class AesUtils {
    private IvParameterSpec iv;
    private SecretKeySpec keySpec;

    public AesUtils(byte[] aesKey) {
        if (aesKey == null || aesKey.length < 16) {
            throw new RuntimeException("错误的初始密钥");
        }
        keySpec = new SecretKeySpec(aesKey, "AES");
        this.iv = new IvParameterSpec(getMD5Bytes(aesKey));
    }

    public AesUtils(byte[] aesKey, byte[] iv) {
        if (aesKey == null || aesKey.length < 16 || (iv != null && iv.length < 16)) {
            throw new RuntimeException("错误的初始密钥");
        }
        if (iv == null) {
            iv = getMD5Bytes(aesKey);
        }
        keySpec = new SecretKeySpec(aesKey, "AES");
        this.iv = new IvParameterSpec(iv);
    }


    public byte[] encryptBytes(String data){
        Cipher cipher;
        byte[] result = null;
        try {
            cipher = Cipher.getInstance("AES/CFB/NoPadding");
            try {
                cipher.init(cipher.ENCRYPT_MODE, keySpec, iv);
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
            result = cipher.doFinal(data.getBytes());

        } catch (NoSuchPaddingException | InvalidKeyException | NoSuchAlgorithmException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return result;
    }

    public String decryptBytes(byte[] data){
        Cipher cipher;
        try {
            cipher = Cipher.getInstance("AES/CFB/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            data = cipher.doFinal(data);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return new String(data);
    }

    public static Key randomKey(int size) {
        byte[] result = null;
        Key  key;
        try {
            KeyGenerator gen = KeyGenerator.getInstance("AES");
            gen.init(size, new SecureRandom());
            result = gen.generateKey().getEncoded();
            key = new SecretKeySpec(result, "AES");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return key;
    }

    public byte[] getMD5Bytes(byte[] data){
        MessageDigest md5 = null;
        try{
            md5 = MessageDigest.getInstance("MD5");
        }catch (Exception e){
            e.printStackTrace();
        }
        String s = new String(data);
        char[] charArray = s.toCharArray();
        byte[] byteArray = new byte[charArray.length];

        for (int i = 0; i < charArray.length; i++) {
            byteArray[i] = (byte) charArray[i];
        }
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++){
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16){
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }

        return hexValue.toString().substring(8,24).getBytes();
    }

    public static SecretKeySpec getKey(String password) throws UnsupportedEncodingException {
        int keyLength = 128;
        byte[] keyBytes = new byte[keyLength / 8];
        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);
        SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
        return key;
    }
}


demo测试类
为了模拟接受端和发送端,另建了个工具类AesUtils2,代码跟上面的一样,就不重复贴了

package com.encryption;

import com.encryption.demo.AesUtils;
import com.encryption.demo.AesUtils2;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import org.junit.jupiter.api.Test;

import java.io.UnsupportedEncodingException;
import java.security.Key;

/**
 * @Description 加密测试类
 * @Author 古大帅哥
 * @Date 2020/5/20 9:33
 */

public class EncryptionTest {

    @Test
    public void test() throws UnsupportedEncodingException {
        //发送端
        Key key1 = AesUtils.getKey("{>|?23432512343dskljffy@123");
        AesUtils aesUtils = new AesUtils(key1.getEncoded());
        String str = "{\"APY18\":\"FE企业版\",\"ISMORSPS_REGISTE\":\"2020-05-19 00:00:00.0\",\"APY17\":\"没有\",\"APY19\":\"22\",\"APY10\":\"场馆中心综合科科长\",\"APY12\":\"56\",\"APY11\":\"13766589422\",\"APY14\":\"6565\",\"APY13\":\"656\",\"APY16\":\"2018-12-26 00:00:00.0\",\"APY15\":\"6565\",\"SERVICE_ID\":\"5\",\"ACCOUNT_MANAGER\":\"徐xx\",\"LOCAL_MAINTAIN_END\":\"2020-05-19 00:00:00.0\",\"CONTRACT_NO\":\"\",\"APY32\":\"D4592347-0A29-530C-AC5A-CC7FF1DE515D\",\"APY31\":\"\",\"APY34\":\"FE6.0.2企业版\",\"APY33\":\"场馆管理中心APP开发项目\",\"UFIDA_PASSWORD\":\"4\",\"APY30\":\"4\",\"SERVICE_PASSWORD\":\"4\",\"LOCAL_MAINTAIN_BEGIN\":\"2018-12-27 00:00:00.0\",\"APY29\":\"是\",\"APY28\":\"4\",\"ISMORSPS_DUE\":\"2020-05-19 00:00:00.0\",\"APY8\":\"深圳信息职业技术学院\",\"APY21\":\"500\",\"APY20\":\"500\",\"ABC01\":\"终端客户\",\"APY23\":\"\",\"APY22\":\"565665\",\"APY4\":\"邓水平\",\"APY25\":\"mysql5.6\",\"ABC04\":\"深信息\",\"APY24\":\"\",\"APY27\":\"2018-12-26 00:00:00.0\",\"APY26\":\"44\",\"ABC06\":\"深圳市龙岗区龙翔大道\"}";
        byte[] encriptBytes = aesUtils.encryptBytes(str);
        //转换成16进制字符串传输
        String s = HexBin.encode(encriptBytes);

        //接收端
        System.out.println("接受端获取密文" + s);
        Key key2 = AesUtils2.getKey("{>|?23432512343dskljffy@123");
        AesUtils2 aesUtils2 = new AesUtils2(key2.getEncoded());
        //16进制转换成2进制
        byte[] decode = HexBin.decode(s);
        byte[] data = aesUtils2.decryptBytes(decode);
        System.out.println("解密后明文:" + new String(data, "UTF-8"));

    }

}

第二天,同事给了链接
https://hutool.cn/docs/#/crypto/%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86-SymmetricCrypto
看了看,默默把昨天的代码删掉,尼玛有这种现成好东西等老子弄完了才给我。。。。
区别是:
一、需要导包
二、更简单

		<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.5</version>
        </dependency>

demo上面文档里面有,由于过于简单,贴个解密的demo,加密基本一样

package com.testhttp.httprequest.controller;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import com.testhttp.httprequest.utils.AesUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;

/**
 * @Description
 * @Author 古大帅哥
 * @Date 2020/5/21 11:30
 */
@Controller
public class HelloController {
    private static String LOCAL_KEY = "11111111";
    @ResponseBody
    @RequestMapping("/getMessage")
    public String getMessage(@RequestParam("data") String data, @RequestParam("key") String key){
        System.out.println("接受密钥:"+ key);
        System.out.println("接受密文:" + data);
        String realkey = SecureUtil.md5(key).substring(7, 15);
        try {
            //解密
            AES aes = new AES(Mode.CTS, Padding.PKCS5Padding, (LOCAL_KEY + realkey).getBytes("UTF-8"), "0102030405060708".getBytes("UTF-8"));
            String ss = aes.decryptStr(data,  CharsetUtil.CHARSET_UTF_8);

            System.out.println("解密后密钥:" + realkey);
            System.out.println("解密后明文:" + ss);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return "hello";
    }
}

其实代码就两行,

AES aes = new AES(Mode.CTS, Padding.PKCS5Padding, (16位长度的字符串”).getBytes("UTF-8"), "0102030405060708".getBytes("UTF-8"));
String ss = aes.decryptStr(data,  CharsetUtil.CHARSET_UTF_8);

加密同样,只要保证那16位字符串的密钥相同即可

所以我做了写其他的骚操作,如demo中的,我传了个动态字符串key,然后再MD5加密(固定返回32位字符串),截取其中的8位进行拼接还原真正的密钥(加密同理),这样被人家拦截也难篡改

在这里插入图片描述

部分请求端代码

public void sendMessage(String id) throws UnsupportedEncodingException {
        String data = getAcceptJsonString(id);

        Properties properties = null;
        try {
            properties = PropertiesLoaderUtils.loadProperties(new ClassPathResource("fy.properties"));
        } catch (IOException e) {
            System.err.println("找不到配置文件");
        }
        String key = properties.getProperty("ENCRYPT_KEY");
        String s2 = RandomUtil.randomString(32);
        String s3 = SecureUtil.md5(s2).substring(7, 15);
        //拼接密钥,加密数据
        AES aes = new AES(Mode.CTS, Padding.PKCS5Padding, (key + s3).getBytes("UTF-8"), "0102030405060708".getBytes("UTF-8"));
        String s1 = aes.encryptHex(data);
        Map<String,Object> map = new HashMap<>();
        map.put("data", "map");
        map.put("key", s2);
        HttpRequest.post("http://localhost:8087/hello")
                .form(data)
                .timeout(20000)
                .execute().body();

    }

执行请求结果
在这里插入图片描述
不得不说,Hutool这个工具库实在太好用,开发效率很高,很多东西比如加密,发起http请求这些东西就帮你封装好,一两行代码就可以执行,给他点个赞👍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Java中,可以使用javax.crypto包中的AES算法来实现文件的加密。 首先,需要导入相应的包: ``` import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.Key; ``` 然后,编写一个方法来实现AES加密文件的功能: ```java public static void encryptFile(String filePath, String key, String outputFilePath) { try { File inputFile = new File(filePath); FileInputStream fis = new FileInputStream(inputFile); byte[] inputBytes = new byte[(int) inputFile.length()]; fis.read(inputBytes); Key aesKey = new SecretKeySpec(key.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, aesKey); byte[] encryptedBytes = cipher.doFinal(inputBytes); FileOutputStream fos = new FileOutputStream(outputFilePath); fos.write(encryptedBytes); fis.close(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } ``` 以上的代码实现了输入一个文件路径(filePath)、一个密钥(key)和一个输出文件路径(outputFilePath),然后加密该文件。 使用方法: ```java public static void main(String[] args) { String filePath = "input.txt"; String key = "0123456789abcdef"; String outputFilePath = "encrypted.txt"; encryptFile(filePath, key, outputFilePath); } ``` 以上代码会将名为"input.txt"的文件加密并输出为"encrypted.txt"。 需要注意的是,以上代码只是简单实现AES加密文件的功能,实际使用中还需要处理异常、进行错误处理等等,提供更完整的功能。 ### 回答2: 要使用Java代码实现AES加密文件,首先需要导入相关的库文件。可以使用Java标准库中的javax.crypto包实现AES加密。以下是一个简单实现示例: ```java import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.Key; import java.util.Arrays; public class AESFileEncryption { // 提供密钥,注意密钥长度必须为16的倍数,因为AES加密算法使用的是128位密钥 private static final byte[] keyBytes = "0123456789abcdef".getBytes(); public static void main(String[] args) { encryptFile("input.txt", "encrypted.txt"); decryptFile("encrypted.txt", "decrypted.txt"); } public static void encryptFile(String inputFile, String outputFile) { try { FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(outputFile); Key key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] inputBytes = new byte[1024]; int bytesRead; while ((bytesRead = fis.read(inputBytes)) != -1) { byte[] outputBytes = cipher.update(inputBytes, 0, bytesRead); if (outputBytes != null) { fos.write(outputBytes); } } byte[] outputBytes = cipher.doFinal(); if (outputBytes != null) { fos.write(outputBytes); } fis.close(); fos.close(); System.out.println("文件加密成功!"); } catch (Exception e) { e.printStackTrace(); } } public static void decryptFile(String inputFile, String outputFile) { try { FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(outputFile); Key key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] inputBytes = new byte[1024]; int bytesRead; while ((bytesRead = fis.read(inputBytes)) != -1) { byte[] outputBytes = cipher.update(inputBytes, 0, bytesRead); if (outputBytes != null) { fos.write(outputBytes); } } byte[] outputBytes = cipher.doFinal(); if (outputBytes != null) { fos.write(outputBytes); } fis.close(); fos.close(); System.out.println("文件解密成功!"); } catch (Exception e) { e.printStackTrace(); } } } ``` 在这个示例中,我们使用了一个预定义的密钥`0123456789abcdef`,你可以根据需要更改这个密钥。该示例将输入文件`input.txt`进行加密,并将加密后的数据写入到输出文件`encrypted.txt`中。然后再将加密后的文件`encrypted.txt`进行解密,并将解密后的数据写入到输出文件`decrypted.txt`中。 请注意,在实际应用中,应该使用更加安全的方法来存储密钥,例如使用密钥管理服务(Key Management Service)或者使用密钥派生函数来生成密钥。此外,还应该考虑更加完善的错误处理和异常处理机制。这个示例只是一个简单的加密文件的实现,实际使用时还需要根据具体需求进行修改和完善。 ### 回答3: 要实现Java代码中的AES加密文件,可以按照以下步骤: 第一步,引入所需的Java库。在代码的开头,需要引入javax.crypto包中的一些类,包括Cipher、SecretKeySpec和IvParameterSpec等。 第二步,指定密钥和IV向量。AES算法需要一个密钥和一个16字节的IV向量。可以自己生成密钥和IV向量,也可以利用密码学安全随机数生成器进行生成。 第三步,创建Cipher对象并初始化。使用AES算法创建一个Cipher对象,并指定加密模式和填充模式。可以使用"CBC"模式,同时选择"PKCS5Padding"填充模式。 第四步,创建输入输出流。使用Java的FileInputStream类创建一个输入流,读取待加密的文件。同时,还需要创建一个FileOutputStream类的对象,用于写入加密后的文件。 第五步,加密处理。在一个循环中,读取输入流中的数据,并使用Cipher对象的update方法对数据进行加密,然后将加密结果写入输出流中。 第六步,处理最后的块。在处理最后的数据块时,需要使用Cipher对象的doFinal方法来进行加密,并将最终的结果写入输出流中。 第七步,关闭流。在加密完成后,需要将输入输出流进行关闭,释放资源。 完整的代码示例如下: ``` import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.SecureRandom; public class AESEncryption { public static void main(String[] args) { String inputFile = "input.txt"; String encryptedFile = "encrypted.txt"; String key = "0123456789ABCDEF"; String iv = "0123456789ABCDEF"; try { FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(encryptedFile); byte[] keyBytes = key.getBytes("UTF-8"); SecretKey secretKey = new SecretKeySpec(keyBytes, "AES"); byte[] ivBytes = iv.getBytes("UTF-8"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); byte[] inputBuffer = new byte[1024]; int bytesRead; while ((bytesRead = fis.read(inputBuffer)) != -1) { byte[] outputBuffer = cipher.update(inputBuffer, 0, bytesRead); if (outputBuffer != null) { fos.write(outputBuffer); } } byte[] outputBuffer = cipher.doFinal(); if (outputBuffer != null) { fos.write(outputBuffer); } fis.close(); fos.flush(); fos.close(); System.out.println("文件加密成功!"); } catch (Exception e) { e.printStackTrace(); } } } ``` 以上就是使用Java代码实现AES加密文件的步骤概述和代码示例。根据实际需求,可以进行适当的修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值