使用ASE+盐对文件流进行加解密,将盐存入到加密后内容中

package com.nt.obs.encryption;

/**
 * @author : fangcong
 * @date : 2023/5/4 15:49
 * @description : 类作用
 **/
import org.springframework.stereotype.Service;

import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

@Service
public class AesEncryptionService implements IEncryptionFile {

    /**
     * 使用固定的密钥
     */
    private static byte[] key = "MyFileSecretKey12345".getBytes();

    /**
     * 加密方法
     * 输入inputStream,将随机盐和iv值添加到对应的加密后的inputStream中,因此无需存储对应的随机盐
     */
    @Override
    public InputStream encrypt(InputStream input) throws Exception {
        // 生成随机盐
        byte[] salt = new byte[16];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(salt);

        // 创建秘钥
        SecretKeySpec secretKeySpec = generateSecretKey(key, salt);

        // 创建IV
        byte[] iv = new byte[16];
        secureRandom.nextBytes(iv);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

        // 构造缓冲流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);

        // 写入随机盐和IV
        bufferedOutputStream.write(salt);
        bufferedOutputStream.write(iv);

        // 执行加密操作
        CipherOutputStream cipherOutputStream = new CipherOutputStream(bufferedOutputStream, cipher);
        byte[] buffer = new byte[1024];
        int len;
        while ((len = input.read(buffer)) != -1) {
            cipherOutputStream.write(buffer, 0, len);
        }
        cipherOutputStream.close();

        // 返回加密后的输入流
        return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    }

    /**
     * 对inputStream进行解密
     * @param input 输入流
     * @return 解密后数据
     * @throws Exception
     */
    @Override
    public InputStream decrypt(InputStream input) throws Exception {
        // 构造缓冲流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(input);

        // 读取随机盐和IV
        byte[] salt = new byte[16];
        bufferedInputStream.read(salt);
        byte[] iv = new byte[16];
        bufferedInputStream.read(iv);

        // 创建秘钥
        SecretKeySpec secretKeySpec = generateSecretKey(key, salt);

        // 初始化解密器
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

        // 执行解密操作
        CipherInputStream cipherInputStream = new CipherInputStream(bufferedInputStream, cipher);
        byte[] buffer = new byte[1024];
        int len;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        while ((len = cipherInputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, len);
        }
        cipherInputStream.close();

        // 返回解密后的输入流
        return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    }

    // 生成秘钥
    private static SecretKeySpec generateSecretKey(byte[] key, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeySpec keySpec = new PBEKeySpec(new String(key).toCharArray(), salt, 65536, 256);
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] keyBytes = secretKeyFactory.generateSecret(keySpec).getEncoded();
        return new SecretKeySpec(keyBytes, "AES");
    }

}

问题

该方式还是为单一加密,也就是每一个文件都是使用相同的key,即使盐不同,iv 不同,获得到了key也能够解密到所有的文件。

双重加密

每一个文件都对应着自己一个key,也就是说每一个文件自己生成一个password,这样必须破解数据库,才有可能破解文件内容。

但是这样不太放心,password应加密保存到数据库,这样就有一个主密钥,那么主密钥应该如何安全进行管理?

反思

以上写法都无法保证百分之百安全,只能提高破解的难度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值