C语言实现异或加/解密的原理
异或原理很简单,异或一次为加密,再异或一次就成了解密了。看下代码
/**
* 加密/解密文件
*
* @param sourcefile 要加密/解密的文件名
* @param secretKey 密钥
* @param targetFile 加密/解密后要保存的文件名
*
* @return 加密成功或失败的数字表示
0:加密失败
1:加密成功
**/
int encryptFile(char *sourcefile, char *secretKey, char *targetFile){
FILE *fpSource, *fpTarget; // 要打开的文件的指针
char buffer[21]; // 缓冲区,用于存放从文件读取的数据
int readCount, // 每次从文件中读取的字节数
keyLen = strlen(secretKey), // 密钥的长度
i; // 循环次数
// 以二进制方式读取/写入文件
fpSource = fopen(sourcefile, "rb");
if(fpSource==NULL){
printf("文件[%s]打开失败,请检查文件路径和名称是否输入正确!\n", sourcefile);
return 0;
}
fpTarget = fopen(targetFile, "wb");
if(fpTarget==NULL){
printf("文件[%s]创建/写入失败!请检查文件路径和名称是否输入正确!\n", fpTarget);
return 0;
}
// 不断地从文件中读取 keyLen 长度的数据,保存到buffer,直到文件结束
while( (readCount=fread(buffer, 1, keyLen, fpSource)) > 0 ){
// 对buffer中的数据逐字节进行异或运算
for(i=0; i<readCount; i++){
buffer[i] ^= secretKey[i];
}
// 将buffer中的数据写入文件
fwrite(buffer, 1, readCount, fpTarget);
}
fclose(fpSource);
fclose(fpTarget);
return 1;
}
avi文件格式
本文所指的视频是avi文件,对别的格式的视频文件应该也适用。AVI文件类型用一个四字符码‘AVI ’来表示。整个AVI文件的结构为:一个RIFF头 + 两个列表(一个用于描述媒体流格式、一个用于保存媒体流数据) + 一个可选的索引块。AVI文件的展开结构大致如下:
RIFF (‘AVI ’
LIST (‘hdrl’
‘avih’(主AVI信息头数据)
LIST (‘strl’
‘strh’ (流的头信息数据)
‘strf’ (流的格式信息数据)
[‘strd’ (可选的额外的头信息数据) ]
[‘strn’ (可选的流的名字) ]
...
)
...
)
LIST (‘movi’
{ SubChunk | LIST (‘rec ’
SubChunk1
SubChunk2
...
)
...
}
...
)
[‘idx1’ (可选的AVI索引块数据) ]
)
具体格式可以用riffpad软件打开看,比如我生成的avi文件格式为如下:
movi列表中存储流的实际数据
视频异或加/解密
视频异或加密有两种思路:一是对生成的视频文件进行整体的加密,比如对test.avi文件进行加密;二是在视频文件生成的过程进行视频流和音频流的加密,这样生成的avi文件直接就是加密的文件。
一、对生成的视频文件进行加/解密
用开头部分C语言实现异或加/解密的原理的代码实现即可
二、对视频文件生成的过程进行视频流和音频流的加密
用ARM或者STM32接上摄像头在拍摄视频时肯定会有视频流和音频流的写buffer,加密就是在视频流和音频流的写buffer时,对buffer进行加密,假设代码大致为如下:
char *secretKey="test";
int keyLen;
keyLen = strlen(secretKey);
//音频流异或加密
for( i =0;i<buffer->data_length/keyLen ; i++)
{
psrc =(char*)buffer->buffer_address+i*keyLen ;
for(j=0;j<keyLen ;j++)
{psrc[j] ^= secretKey[j];}
}
write_audio_frames(infor, buffer); //音频流写buffer
//视频流异或加密
for( i =0;i<buffer->data_length/keyLen ; i++)
{
psrc =(char*)buffer->buffer_address+i*keyLen ;
for(j=0;j<keyLen ;j++)
{psrc[j] ^= secretKey[j];}
}
write_video_frames(infor, buffer); //视频流写buffer
解密就是对avi文件movi列表中存储流的实际数据进行解密,注意只解密movi列表中的数据,别的数据不解密,比如idx1(可选的avi索引块数据)不解密。
解密程序大致为:
**/
int decryptFile(char *sourcefile, char *secretKey, char *targetFile){
FILE *fpSource, *fpTarget; // 要打开的文件的指针
char buffer[21]; // 缓冲区,用于存放从文件读取的数据
int readCount, // 每次从文件中读取的字节数
keyLen = strlen(secretKey), // 密钥的长度
i; // 循环次数
// 以二进制方式读取/写入文件
fpSource = fopen(sourcefile, "rb");
if(fpSource==NULL){
printf("文件[%s]打开失败,请检查文件路径和名称是否输入正确!\n", sourcefile);
return 0;
}
fpTarget = fopen(targetFile, "wb");
if(fpTarget==NULL){
printf("文件[%s]创建/写入失败!请检查文件路径和名称是否输入正确!\n", fpTarget);
return 0;
}
// 不断地从文件中读取 keyLen 长度的数据,保存到buffer,直到文件读到buffer中数据为"movi"
while ((readCount = fread(inbuf, 1, keyLen, fpSource ))>0 && !((inbuf[0] == 'm') && (inbuf[1] == 'o') && (inbuf[2] == 'v') && (inbuf[3] == 'i'))){
// 将buffer中的数据写入文件
fwrite(inbuf, 1, readCount, fpTarget);
}
fwrite(inbuf, 1, readCount, fpTarget);//将"movi"写入文件
//对movi中实际数据进行异或运算,直到读到buffer中数据为"idx1"
while ((readCount = fread(inbuf, 1, keyLen, fpSource ))>0 && !((inbuf[0] == 'i') &&(inbuf[1] == 'd') && (inbuf[2] == 'x') && (inbuf[3] == '1'))){
// 对buffer中的数据逐字节进行异或运算
for (i = 0; i<readCount; i++){
inbuf[i] ^= secretKey[i];
}
// 将buffer中的数据写入文件
fwrite(inbuf, 1, readCount, fpTarget);
}
fwrite(inbuf, 1, readCount, fpTarget);//将"idx1"写入文件
//将idx1后边的所有数据写入文件,直到文件结束
while ((readCount = fread(inbuf, 1, keyLen, fpSource )) > 0){
// 将buffer中的数据写入文件
fwrite(inbuf, 1, readCount, fpTarget);
}
fclose(fpSource);
fclose(fpTarget);
return 1;
}