使用FFMPEG对TS封装H264编码的文件进行NAL的加密

这篇博客介绍了如何使用FFmpeg-3.3.3和openssl-1.0.2l对TS封装的H264编码文件进行NAL单元的AES-128-CBC加密和解密。文章详细展示了全文件加解密接口的实现,包括读取、解密、加密、写入等步骤,并特别提到了在处理过程中防止二义性的方法。同时,还讨论了在处理过程中可能遇到的数据长度变化问题以及如何处理解密后的数据。最后,代码中包含了针对NAL加密后的TS文件,使用新密钥再次加密的接口设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用ffmpeg-3.3.3和openssl-1.0.2l对TS封装H264编码的文件进行NAL的加密,以下是我实现的接口代码:
//#include "StdAfx.h"
#include "TroubleShoot.h" 
#ifdef __cplusplus //
extern "C"{
#endif

#include "TSEncrypt.h"

#include 

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"

#include 
#include 
#include 
#include 

static FILE *fp_stream=NULL;								//输出文件句柄
static unsigned char s_cp_key[SUMA_KEY_AND_IV_LEN]={0};		//cpck
static unsigned char s_cp_iv[SUMA_KEY_AND_IV_LEN]={0};		//cpiv
static int s_en_type=0;										//读文件数据后是否要进行解密处理
static bool enable_encrypt_card=false;						//是否启用硬件加密卡

#if 1
//加密
static int aescbc128_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
               unsigned char *iv, unsigned char *ciphertext)
{
	if((plaintext==NULL)||(plaintext_len==0)||(key==NULL)||(iv==NULL)||(ciphertext==NULL))
		return -1;
	if(enable_encrypt_card)
	{
		bool status=false;// = AESEncryptInCBC(plaintext_len,(const BYTE *)plaintext,(const BYTE *)key,(const BYTE *)iv,(BYTE *)ciphertext);
		if(status)
			return plaintext_len;
		else
			return -1;
	}
	else
	{
		EVP_CIPHER_CTX *ctx=NULL;   
		int len=0;   
		int ciphertext_len=0;

		ctx = EVP_CIPHER_CTX_new();
		if(ctx==NULL)
			return -1;
		EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
		EVP_CIPHER_CTX_set_padding(ctx, 0);
		EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len);
		ciphertext_len = len;
		EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
		ciphertext_len += len;
		EVP_CIPHER_CTX_free(ctx);
    
		return ciphertext_len;
	}
}

//解密
static int aescbc128_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
               unsigned char *iv, unsigned char *plaintext)
{
	if((ciphertext==NULL)||(ciphertext_len==0)||(key==NULL)||(iv==NULL)||(plaintext==NULL))
		return -1;
	if(enable_encrypt_card)
	{
		bool status=false;// = AESDecryptInCBC(ciphertext_len,(const BYTE *)ciphertext,(const BYTE *)key,(const BYTE *)iv,(BYTE *)plaintext);
		if(status)
			return ciphertext_len;
		else
			return -1;
	}
	else
	{
		EVP_CIPHER_CTX *ctx=NULL;
		int len=0;
		int plaintext_len=0;  

		ctx = EVP_CIPHER_CTX_new();  
		if(ctx==NULL)
			return -1;
		EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
		EVP_CIPHER_CTX_set_padding(ctx, 0);
		EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
		plaintext_len = len; 
		EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
		plaintext_len += len;   
		EVP_CIPHER_CTX_free(ctx);
    
		return plaintext_len;
	}
}
#endif

/*全文件加解密接口*/
int Suma_full_file_encrypt_or_decrypt(char *in_path,char *out_path,unsigned char *key,unsigned char *iv,int flag)
{
	struct stat sta_buff;	
	int ret=0;
	unsigned char *tmp_buf=NULL;
	unsigned int tmp_buf_size=SUMA_READ_DATA_LEN;	
	unsigned int read_len=0;
	unsigned int write_len=0;
	unsigned int total_write_len=0;
	unsigned int processed_len=0;
	unsigned int tmp_len=0;
	FILE* fp_r=NULL;
	FILE* fp_w=NULL;
	unsigned char tmp_iv[SUMA_KEY_AND_IV_LEN]={0};

	DvtLog(DVT_MSG_TYPE_INFORMATION,"全文件加解密操作开始");
	if((in_path==NULL)||(out_path==NULL)||(key==NULL)||(iv==NULL))
	{
		DvtLog(DVT_MSG_TYPE_ERROR,"全文件加解密的参数错误!");
		ret=-1;
		return ret;
	}
	ret = stat(in_path, &sta_buff);
	if(ret != 0)
	{
		DvtLog(DVT_MSG_TYPE_ERROR,"全文件加解密时输入文件不存在!");
		return ret;
	}
	fp_r=fopen(in_path,"rb");
	if(fp_r == NULL)
	{
		DvtLog(DVT_MSG_TYPE_ERROR,"全文件加解密时打开输入文件失败!");
		ret=-1;
		goto end;
	}

	fp_w=fopen(out_path,"wb+");
	if(fp_w == NULL)
	{
		DvtLog(DVT_MSG_TYPE_ERROR,"全文件加解密时打开输出文件失败!");
		ret=-1;
		goto end;
	}
	tmp_buf = (unsigned char *)malloc(tmp_buf_size);
	if(tmp_buf == NULL)
	{
		DvtLog(DVT_MSG_TYPE_ERROR,"全文件加解密时分配缓存失败!");
		ret=-1;
		goto end;
	}
	while(sta_buff.st_size>total_write_len)
	{
		read_len=fread(tmp_buf,1,tmp_buf_size,fp_r);
		tmp_len=read_len/SUMA_KEY_AND_IV_LEN*SUMA_KEY_AND_IV_LEN;
		if(flag == 0)
		{	
			processed_len = aescbc128_encrypt (tmp_buf, tmp_len, key, iv,tmp_buf);
			memcpy(iv,tmp_buf+tmp_len-SUMA_KEY_AND_IV_LEN,SUMA_KEY_AND_IV_LEN);
		}
		else
		{
			memcpy(tmp_iv,tmp_buf+tmp_len-SUMA_KEY_AND_IV_LEN,SUMA_KEY_AND_IV_LEN);
			processed_len = aescbc128_decrypt (tmp_buf, tmp_len, key, iv,tmp_buf);
			memcpy(iv,tmp_iv,SUMA_KEY_AND_IV_LEN);
		}
		
		if(processed_len != tmp_len)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值