Java加解密视频(AES算法)的实现

认识AES

先来看看什么是AES算法

什么是AES

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准

AES简介

这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一 [1] 。
该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijdael之名命之,投稿高级加密标准的甄选流程。(Rijdael的发音近于 “Rhine doll”。)

AES的加密模式及个模式加密的优缺点

AES的分组长度是128bit,三种可选密钥长度128bit,192bit和256bit,轮数分别为10、12和14
常见五中工作模式:

ECB (ElectronicCodebook,电子密码本)
优点:简单、可并行计算、误差不传递
缺点:不能隐藏明文模式(比如图像加密轮廓仍在)、主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
用途:需要并行加密的应用

CBC (Cipher Block Chaining,密码分组链接)∶
优点:不容易主动攻击(误差传递)、适合长报文,是SSL、IPSec标准
缺点:无法并行、误差传递
用途:长报文传输,SSL和IPSec

CFB (CipherFeedback,密码反馈)︰
优点:不容易主动攻击(误差传递),分组转变为流模式,可加密小于分组数据缺点:无法并行、误差传递

OFB (OutputFeedback,输出反馈)︰
优点:分组转为流模式、可加密小于分组数据
缺点:主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
用途:通信信道质量不高时使用,比如卫星通信

CTR (Counter,计数器模式)∶
描述:计算器模式不常见,在CTR模式中,有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次
优点:并行、一次一密、不传递误差
缺点:主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)

总结

分组模式: ECB、CBC和CTR;
模式: CFB、OFB

传递误差: CBC、CFB
不传递误差: ECB、OFB和CTR

可并行: ECB、CTR
不可并行: CBC、OFB、CFB

简单的伪代码及部分实现代码

加密视频

其实就是用字节流处理,没什么很大的难点 唯一需要注意的是,加解密字节数组的一些注意点。

加解密的伪代码

加密
public void encryptVideo(String filePath, String password) throws Exception {
        //声明输入输出流为null -- 伪代码

        try {
          	//在这里实例化输入输出流-- 伪代码
          	
            //读取文件和写入文件必要的参数
            //文件的长度
            long fileSize = new File(filePath).length();
         	//+1是为了保证 long不为整数时 向上取整
            byte[] readByte = new byte[(int)fileSize + 1];
            
            //从输入流中读取字节数组 
            bfInStream.read(readByte);
            
            //获取使用Aes加密后的字节数组-- 伪代码
            // 这里是额外的操作  比如可以再给字节数组进行自定义的加密操作  可有可无-- 伪代码
            //输出流的写入加密后的字节数组-- 伪代码

        }catch (FileNotFoundException fex) {
           //这里做日志记录
        }catch (Exception ex) {
            //其他报错
        }
        finally {
			//对应流的关闭
            }
        }
    }
解密

其实流程和加密视频差不多,但是需要修改一些小地方

//获取文件长度
long fileSize = new File(filePath).length();
//保证字节数组为16的整数倍 
byte[] readByte = 
new byte[(int)fileSize + (16 - (int)fileSize%16)];

字节数组的加解密

public byte[] enAesForVideo(byte[] videoByte, String password) throws Exception {
        byte[] enCode = null;
        try {
            //生成一个AES算法的密钥生成器
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            //使用给定的随机源(可以看作你自己设置的密码,但对于程序而言,你输入的只是一个生成密钥的”种子“)
            // 初始化该密钥生成器(生成密钥长度为128位)
            kg.init(128, new SecureRandom(password.getBytes("UTF-8")));
            //生成一个种子密钥。
            SecretKey ruleKey = kg.generateKey();
            //获取编码后的种子密钥
            byte[] skCode = ruleKey.getEncoded();
            //从给定的字节数组构造一个aes密钥
            SecretKey aesKey = new SecretKeySpec(skCode, "AES");
            //该类提供加密和解密的加密密码的功能
            Cipher cp = Cipher.getInstance("AES");
            //用密钥初始化
            cp.init(Cipher.ENCRYPT_MODE, aesKey);
            //真正的加密操作
            enCode = cp.doFinal(videoByte);
        } catch (Exception ex) {
            //在这里进行出错的日志记录
            ex.printStackTrace();
        }
        return enCode;
    }

解密字节数组

与加密字节数组唯一不同的是以下这两项 其他一样

 //该类提供加密和解密的加密密码的功能。 
 //它构成了Java加密扩展(JCE)框架的核心。
  Cipher cp = Cipher.getInstance("AES/ECB/NoPadding");
  //设置为解密模式
  cp.init(Cipher.DECRYPT_MODE, aesKey);

遇到的问题

分段读取文件加密,导致解密后文件无法读出

直接一次性读入整个文件。(感觉上是分段加密后导致某些字符与换行符什么的特殊字符冲突)

解密时,未指定解密模式导致解密失败

将创建实例时的

Cipher cipher = Cipher.getInstance("AES");

将参数改为以下内容即可

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

解密时,需要输入的字节数组为16的整数倍

在创建临时字节数组用于,取得读出的数据时,加上参数,使得字节数组为16的整数倍。

 long fileSize = new File(filePath).length();
 byte[] readByte = 
    new byte[(int)fileSize + (16 - (int)fileSize%16)];
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然!以下是使用AES算法实现文件加密和解密的Java代码示例: ```java import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileEncryptionDecryption { private static final String ALGORITHM = "AES"; public static void encryptFile(String inputFile, String outputFile, String key) throws IOException { try { SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(outputFile); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { byte[] output = cipher.update(buffer, 0, bytesRead); if (output != null) { outputStream.write(output); } } byte[] output = cipher.doFinal(); if (output != null) { outputStream.write(output); } inputStream.close(); outputStream.flush(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } public static void decryptFile(String inputFile, String outputFile, String key) throws IOException { try { SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(outputFile); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { byte[] output = cipher.update(buffer, 0, bytesRead); if (output != null) { outputStream.write(output); } } byte[] output = cipher.doFinal(); if (output != null) { outputStream.write(output); } inputStream.close(); outputStream.flush(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { String inputFile = "plaintext.txt"; String encryptedFile = "encrypted.txt"; String decryptedFile = "decrypted.txt"; String key = "mySecretKey"; try { encryptFile(inputFile, encryptedFile, key); System.out.println("File encrypted successfully."); decryptFile(encryptedFile, decryptedFile, key); System.out.println("File decrypted successfully."); } catch (IOException e) { e.printStackTrace(); } } } ``` 在这个示例中,我们添加了一个`decryptFile`方法来实现文件解密。它与`encryptFile`方法类似,只是在`Cipher`对象的初始化中使用了`Cipher.DECRYPT_MODE`模式。 请注意,为了简化示例,我们使用相同的密钥来进行加密和解密。在实际应用中,你可能需要更安全的密钥管理和分发机制。另外,为了使代码更健壮,你可能还需要处理异常、使用合适的缓冲区大小等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值