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

数据加密解密是一个常用的功能,如果你不希望让别人看到文件中的内容,可以通过密钥(也称”密码“)将文件的内容加密。比如文本文件(.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;
}

 

 

posted @ 2024-03-16 22:44  猪油哥  阅读(39)  评论(0编辑  收藏  举报