首页 > 其他分享 >使用位运算对数据或文件进行加密

使用位运算对数据或文件进行加密

时间:2024-03-16 22:56:59浏览次数:24  
标签:文件 加密 运算 pCryptedBlock vecPlainData char 密钥 BLOCK

数据加密解密是一个常用的功能,如果你不希望让别人看到文件中的内容,可以通过密钥(也称”密码“)将文件的内容加密。比如文本文件(.txt),加密前的内容是能够读懂的,加密后的内容是”乱码“,都是一些奇怪的字符,根本无法阅读。

数据加密解密的原理也很简单,就是使用异或运算。请先看下面的代码:

#include<stdio.h>
#include<stdlib.h>
int main() 
{
#pragma warning(suppress : 4996)
    char plaintext = 'a'; //明文
    char secretkey = '!'; //密钥
    char ciphertext = plaintext ^ secretkey; //密文
    char decodetext = ciphertext ^ secretkey; //解密后的字符
    char buffer[9];
 
    printf("            char    ASCII\n");
    // itoa()用来将数字转换为字符串,可以设定转换时的进制(基数)
    // 这里将字符对应的ascii码转换为二进制
    printf(" plaintext   %c     %7s\n", plaintext, itoa(plaintext, buffer, 2));
    printf(" secretkey   %c     %7s\n", secretkey, itoa(secretkey, buffer, 2));
    printf("ciphertext   %c     %7s\n", ciphertext, itoa(ciphertext, buffer, 2));
    printf("decodetext   %c     %7s\n", decodetext, itoa(decodetext, buffer, 2));
    return 0;
 
}

 

运行结果:

            char    ASCII
 plaintext   a     1100001
 secretkey   !      100001
ciphertext   @     1000000
decodetext   a     1100001

 

看到了吗,plaintext 与 decodetext相同,也就是说,两次异或运算后还是原来的结果。

这就是加密的关键技术:

1、通过一次异或运算,生成密文,密文没有可读性,与原文风马牛不相及,这就是加密;

2、密文再经过一次异或运算,就会还原成原文,这就是解密的过程;

3、加密和解密需要相同的密钥,如果密钥不对,是无法成功解密的。

上面的加密算法称为对称加密算法,加密和解密使用同一个密钥。

 

如果加密和解密的密钥不同,则称为非对称加密算法。在非对称算法中,加密的密钥称为公钥,解密的密钥称为私钥,只知道公钥是无法解密的,还必须知道私钥。

注意:程序中的 itoa() 位于 stdlib.h 头文件,它并不是一个标准的C函数,只有Windows下有,

使用异或运算对数据及文件进行加密处理

typedef struct CRYPT_BLOCK 
{
  DWORD    dwSize;    // Data的
  DWORD    dwKey;    // 密钥 循环使用DWORD的每个字节来进行加密 详情见XorEncrypt
  char    chData[1];    // 加密后的数据
} CRYPT_BLOCK, *PCRYPT_BLOCK;

typedef boost::shared_ptr<Json::Value> JsonSharedPtr;

 

一个数异或另一个数两次后,该数保持不变。即:

c = a^b;
c = c^b;
c == a;

 

这一规律就是使用异或运算对数据及文件进行加密处理的基本原理。

bool XorEncrypt(const char* pKey, DWORD dwCbKey, const char* pIn, DWORD dwCbSize, char* pOut)
{
  if (pIn == NULL || pOut == NULL || pKey == NULL) {
    return false;
  }

  for (DWORD i = 0; i < dwCbSize; ++i) {
    pOut[i] = pIn[i] ^ pKey[i % dwCbKey];
  }

  return true;
}

 

pKey为密钥数据指针,dwCbKey为密钥数据长度,pIn为需要加密的数据指针,dwCbSize为需要加密的数据长度,pOut为加密后数据指针

加密函数:

vector<char> Encrypt(const vector<char> &vecPlainData)
{
    vector<char> vecCryptedData;

    do {

        if (vecPlainData.empty()) {
            break;
        }

        if (UINT_MAX - vecPlainData.size() < sizeof(CRYPT_BLOCK) - 1) {
            //溢出
            break;
        }

        //文件里的加密信息是分成一个一个数据块CRYPT_BLOCK存放的
        //只是用异或简单加密一下,具体加密流程见XorEncrypt函数
        DWORD dwCryptBlockSize = sizeof(CRYPT_BLOCK) - 1 + vecPlainData.size();

        vecCryptedData.resize(dwCryptBlockSize);
        PCRYPT_BLOCK CryptedBlock = (PCRYPT_BLOCK)&vecCryptedData[0];
        CryptedBlock->dwKey = GenerateKey();
        CryptedBlock->dwSize = vecPlainData.size();

        bool bOk = XorEncrypt((char*)&CryptedBlock->dwKey, sizeof CryptedBlock->dwKey, &vecPlainData[0], vecPlainData.size(), CryptedBlock->chData);
        if (!bOk) {
            vecCryptedData.clear();
        }
    } while (false);

    return vecCryptedData;
}

 

解密函数:

vector<char> Decrypt(const vector<char> &vecCryptedData)
{
    PCRYPT_BLOCK pCryptedBlock = NULL;
    vector<char> vecPlainData;

    do {
        if (vecCryptedData.size() < sizeof *pCryptedBlock) {
            break;
        }

        pCryptedBlock = (PCRYPT_BLOCK)&vecCryptedData[0];

        if (UINT_MAX - pCryptedBlock->dwSize < sizeof *pCryptedBlock - 1) {
            //溢出
            break;
        }
        //运算符优先级 sizeof > 加减 > 不等
        if (pCryptedBlock->dwSize + sizeof *pCryptedBlock - 1 != vecCryptedData.size()) {
            break;
        }

        vecPlainData.resize(pCryptedBlock->dwSize);
        bool ok = XorEncrypt((char *)&pCryptedBlock->dwKey, sizeof pCryptedBlock->dwKey, pCryptedBlock->chData, pCryptedBlock->dwSize, &vecPlainData[0]);
        if (!ok) {
            vecPlainData.clear();
        }

    } while (false);

    return vecPlainData;
}

 

生成Key:

BYTE CHipsLogQueue::RandomByte()
{
    unsigned int random;
    rand_s(&random);
    return BYTE(random);
}

DWORD CHipsLogQueue::GenerateKey()
{
    DWORD Key = 0;

    for (int i = 0; i < 4; ++i) {
        ((BYTE *)(&Key))[i] = RandomByte();
    }

    return Key;
}

 

 

标签:文件,加密,运算,pCryptedBlock,vecPlainData,char,密钥,BLOCK
From: https://www.cnblogs.com/-hz01/p/18077811

相关文章

  • 题目 2154: 取余运算
    题目描述:输入b,p,k的值,求b^pmodk的值。其中b,p,k×k为长整型数。解题思路:如果指数为奇数,那么结果乘以当前的底数,指数除以2(整除运算)。如果指数为偶数,那么底数变为原来底数的平方,指数除以2。代码:分治算法packagelanqiao;importjava.math.BigInteger;importjava.util......
  • 华为OD机试 C++ -文件缓存系统
    文件缓存系统前言:本专栏将持续更新互联网大厂机试真题,并进行详细的分析与解答,包含完整的代码实现,希望可以帮助到正在努力的你。关于大厂机试流程、面经、面试指导等,如有任何疑问,欢迎联系我,wechat:steven_moda;email:[email protected];备注:CSDN。题目描述请设计一个文件缓......
  • 命令行生成jar文件
    做IT也二十年有余了,一直做着运维工作,编程仅是业余兴趣,水平就是在HelloWorld的基础上多做几个练习,行在各语言都能试试手,偶尔也能做些提高效率小工具,多是味都没怎么嚼就新版本了,人也白发生了...运维吗,效率在先,什么容易就用什么,c#,php,autoit,shell,bat,vba,sql,powershell,python,唯java总......
  • 【git】删除index记录,保留本地文件
    一、场景就是想删除某个文件的提交,但是保留本地文件  二、方法https://git-scm.com/docs/git-rm/zh_HANS-CN  三、示例#这将会从版本控制中删除文件,但保留在本地文件系统中。gitrm--cached<file>#如果你想要删除多个文件并保留本地文件,可以这样操作:git......
  • QSVRMGMT.DLL文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个QSVRMGMT.DLL文件(挑选合适的版本文件)把它......
  • provsvc.dll文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个provsvc.dll文件(挑选合适的版本文件)把它放......
  • Windows7系统consent.exe文件丢失问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个consent.exe文件(挑选合适的版本文件)把它放......
  • Windows7系统vdsutil.dll文件丢失问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个vdsutil.dll文件(挑选合适的版本文件)把它放......
  • 华为OD机试Js - 文件缓存系统
    文件缓存系统前言:本专栏将持续更新互联网大厂机试真题,并进行详细的分析与解答,包含完整的代码实现,希望可以帮助到正在努力的你。关于大厂机试流程、面经、面试指导等,如有任何疑问,欢迎联系我,wechat:steven_moda;email:[email protected];备注:CSDN。题目描述请设计一个文件缓......
  • 实验1 C语言开发环境使用和数据类型,运算符,表达式
    #include<stdio.h>intmain(){printf("O\n");printf("<H>\n");printf("II\n");return0;}#include<stdio.h>intmain(){printf("O\n");printf("<H>\n");print......