异或加密(XOR)原理及实现


什么是异或加密

异或加密是一种加密算法,利用了计算机中的异或计算,异或计算(符号记为 ‘^’)的原理是,相同为 0,不同为 1

0 ^ 0 = 0
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1

由于 1 ^ 0 或 0 ^ 1 的结果都为 1,因此,不能直接由结果 1 推出原来的明文到底是 0 还是 1,达到保护明文的目的。

异或加密特性

简单异或密码(英语:simple XOR cipher)是密码学中一种简单的加密算法,它按照如下原则进行运算:

  1. A ^ 0 = A
  2. A ^ A = 0
  3. (A ^ B) ^ C = A ^ (B ^ C)
  4. (B ^ A) ^ A = B ^ 0 = B // 明文 B;密码 A

从原理 4 可得,对同一个明文 B,使用密钥 A 对其进行两次异或运算,可得到明文 B,我们正是利用了这一特性,进行实现加密解密

异或加密算法

异或加密算法由 3 部分组成,分别是
明文
密钥
异或运算规则
流程是通过遍历明文的每一个字符,并按照异或运算规则从密钥中取出一个或多个字符,与明文的字符进行异或运算,将异或的结果合成一个新的字符串,
但是由于异或运算的特性,有可能异或运算后为一个不可见字符,就可能无法通过字符串传递密文了,因此这里引入了 base64 编码,因为 base64 编码后的字符串都是可见字符,

base64编码

,base64编码是把3个8bit(38=24bit)编码成4个6bit(46=24bit),并在每个6bit高位添加两个0构成一个8bit,然后换算成10进制,反查编码表即可得到对应的编码。由于2^6=64,即6bit的最大值是63,所以只需要64(0~63)个ASCII字符即可表示所有编码,因此得名base64编码。
在这里插入图片描述
下面来举例说明:
有一个字符串”abcd”

      a         b         c        d
ASCII:    0x61      0x62      0x63     0x64
8bit:  01100001   01100010  01100011 0110 0100
6bit:  011000   010110  001001 100011  011001 000000 = =
十进制:  24       22      9       35     25      0
查码表得: Y        W      J       j      Z       A   =  =
最终结果:YWJjZA==

你可能注意到了,是每3个8bit进行一次编码,如果编码到最后不够3字节怎么办?base64编码规定,对于不够3个8bit的,编码完成后少几个6bit添几个”=”,这会有两种情况:

1.18bit(假设为xxxxxxxx):
编码完成后得到:
xxxxxx xx0000 = =
此时还缺2个6bit,因此在末尾添加“==2.28bit(假设为xxxxxxxx yyyyyyyy):
2.28bit(假设为xxxxxxxx yyyyyyyy):
编码后得到:
xxxxxx xxyyyy yy0000 =
此时还缺1个6bit,因此在末尾添加“=

这也是为什么base64编码完成后面会有1到2个”=”。

加解密

所以加密算法变成:
明文与密钥按照异或运算规则进行异或运算,产生密文
将得到的密文进行base64 编码,最后返回
而解密算法相应的变成:
将密文进行 base64 解码,得到原始的密文
将密文按照相同的异或运算规则与密文进行异或,得到明文

异或运算算法

异或运算算法是为了解决明文与密文如何进行异或运算的问题,因为明文和密文长度可能不一样,如何保证明文的每个字符都有与之对应的密文字符进行异或,并且在解密时保证按照相同的算法进行异或运算得到明文,是异或运算算法要考虑的,这里我们会用到一种新的运算,叫 取余,这里不考虑为负数的情况
取余运算(通常记为 %),表示的是 被除数 除以 除数之后的余数,比如 8 / 5 = 1 余 3,因此 8 % 5 = 3,另外取余运算规定如果被除数小于除数,那么取余结果就为被除数,因此 5 % 8 = 5,来看下面的例子:

0%3=0 
1%3=1
2%3=2
3%3=0
4%3=1
5%3=2
6%3=0
7%3=1

你们发现了吗,结果总是 0,1,2 的循环,我们就可以通过让明文每个字符的索引对密文的总长度取余,得到的结果作为密文的索引下标,取出对应的密文字符,与明文字符进行异或运算就可以啦
看下面这个例子吧请添加图片描述

代码实现

#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
#include <bitset>
#include <cstring>
#include <openssl/bio.h>//使用 OpenSSL 库中的 BIO 函数来处理 Base64 编码和解码。你需要在编译时链接 OpenSSL 库(-lssl -lcrypto)。
#include <openssl/evp.h>
#include <openssl/buffer.h>//BUF_MEM 结构体是一个不完整类型(即前向声明),在使用之前需要包含相应的头文件。

// Base64 编码和解码的函数
std::string Base64Encode(const std::string& input) {
    BIO *bio, *b64;
    BUF_MEM *bptr;
    std::string output;

    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new(BIO_s_mem());
    bio = BIO_push(b64, bio);
    BIO_write(bio, input.data(), input.size());
    BIO_flush(bio);
    BIO_get_mem_ptr(bio, &bptr);

    output.assign(bptr->data, bptr->length - 1);
    BIO_free_all(bio);
    return output;
}



//BIO_read 函数在读取解码后的数据时可能没有正确处理输入的长度,或者输出的字符串长度没有正确计算。
std::string Base64Decode(const std::string &input) {
    BIO *bio, *b64;
    char *buffer = (char*)malloc(input.length());
    memset(buffer, 0, input.length());

    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new_mem_buf(input.c_str(), input.length());
    BIO_push(b64, bio);
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

    int decoded_size = BIO_read(b64, buffer, input.length());
    BIO_free_all(b64);

    std::string output(buffer, decoded_size);
    free(buffer);
    return output;
}


// XOR 加密和解密函数:XORCipher 函数执行 XOR 操作来加密或解密数据。
std::string XORCipher(const std::string& text, const std::string& key) {
    std::string result(text.size(), '\0');
    size_t keyLength = key.size();
    for (size_t i = 0; i < text.size(); ++i) {
        result[i] = text[i] ^ key[i % keyLength];
    }
    return result;
}
//Encode 函数先进行 XOR 加密,然后进行 Base64 编码。
std::string Encode(const std::string& plainText, const std::string& key) {
    std::string encryptedText = XORCipher(plainText, key);
    return Base64Encode(encryptedText);
}
//Decode 函数先进行 Base64 解码,然后进行 XOR 解密。
std::string Decode(const std::string& cipherText, const std::string& key) {
    std::string decodedBase64 = Base64Decode(cipherText);
    return XORCipher(decodedBase64, key);
}

int main() {
    std::string key = "3567d8cndkei%*x9(-32[]KDF(32222";
    std::string plainText = "Hello World!";

    std::string encodedText = Encode(plainText, key);
    std::cout << "Encoded: " << encodedText << std::endl;

    std::string decodedText = Decode(encodedText, key);
    std::cout << "Decoded: " << decodedText << std::endl;

    return 0;
}

  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值