C语言实现视频异或加/解密

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;
}   

猜你喜欢

转载自blog.csdn.net/king_jie0210/article/details/73603932