谈谈异或加密

0. 前言

本文包括如下几个内容:

  • 异或算法
  • 异或加密
  • 两个整数交换问题


1. 异或算法

异或是数字逻辑中的基本概念,也是每种编程语言都支持的基本运算。基本原理就是,对于数字1和0有如下的运算公式:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 1 ^ 1 = 0  
  2. 0 ^ 0 = 0  
  3. 1 ^ 0 = 1  
  4. 0 ^ 1 = 1  

很自然地,这个运算可以扩展到一长串码流上。


更常见的是字节一级或整数的异或运算,可以参考相应的编程语言的相关介绍。


2. 异或加密

异或加密是最简单的一种加密方法,简单来讲,假定有一串码流A,然后可以用key进行加密,把加密后的数据保存或发送出去。而在读取加密数据之后,再用key进行解密。

直接用代码更容易理解,如下示例:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. static void xor_encrypt(char *data, char *key, int len)  
  5. {  
  6.     int i = 0;  
  7.     for (i = 0; i < len; i++) {  
  8.         data[i] ^= key[i];  
  9.     }  
  10. }  
  11.   
  12. static void dumphex(const unsigned char *data, int len)  
  13. {  
  14.     int i;  
  15.     for (i = 0; i < len; i++) {  
  16.         printf("%02X", data[i]);  
  17.     }  
  18.     printf("\n");  
  19. }  
  20.   
  21. static unsigned char* get_random_key(int len)  
  22. {  
  23.     int i = 0;  
  24.     unsigned char* buffer = (unsigned char*)malloc(len);  
  25.     for (i = 0; i < len; i++) {  
  26.         buffer[i] = rand() % 10 + '0';  
  27.     }  
  28.   
  29.     return buffer;  
  30. }  
  31.   
  32. int main()  
  33. {  
  34.     unsigned char data[] = "hello, xor!";  
  35.     int len = sizeof(data);  
  36.   
  37.     unsigned char *key;  
  38.   
  39.     key = get_random_key(len);  
  40.     printf("original data: %s\n", data);  
  41.     printf("original data (hex): ");  
  42.     dumphex(data, len);  
  43.   
  44.     xor_encrypt(data, key, len);  
  45.     printf("encrypted data: %s\n", data);  
  46.     printf("encrypted data (hex): ");  
  47.     dumphex(data, len);  
  48.   
  49.     xor_encrypt(data, key, len);  
  50.     printf("original data: %s\n", data);  
  51.     printf("original data (hex): ");  
  52.     dumphex(data, len);  
  53.   
  54.     free(key);  
  55.   
  56.     return 0;  
  57. }  

运行结果:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. original data: hello, xor!  
  2. original data (hex): 68656C6C6F2C20786F722100  
  3. encrypted data: [S[Y\JVC7  
  4. encrypted data (hex): 5B535B595C19164A56431337  
  5. original data: hello, xor!  
  6. original data (hex): 68656C6C6F2C20786F722100  

3. 交换两个整数

有些TX在面试的时候,可能会遇到这个问题,即:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 有两个整数a和b,如何在不引入第三个变量的情况下,交换两个整数的值?  

在了解了前面介绍的异或的概念之后,这个问题就迎刃而解。直接给出代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. void swap(int &x, int &y)  
  4. {  
  5.     x ^= y;  
  6.     y ^= x;  
  7.     x ^= y;  
  8. }  
  9.   
  10. int main()  
  11. {  
  12.     int x = 55555;  
  13.     int y = 33333;  
  14.   
  15.     printf("first, x = %d, y = %d\n", x, y);  
  16.     swap(x, y);  
  17.     printf("and now, x = %d, y = %d\n", x, y);  
  18.   
  19.     return 0;  
  20. }  

执行结果:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. flying-bird@flying-bird:~/docs/The_Road_to_Cpp/src$ g++ swap_ints.cc   
  2. flying-bird@flying-bird:~/docs/The_Road_to_Cpp/src$ ./a.out   
  3. first, x = 55555, y = 33333  
  4. and now, x = 33333, y = 55555  
  5. flying-bird@flying-bird:~/docs/The_Road_to_Cpp/src$   

4. 再谈key

前面谈到异或加密的时候,提到的密钥key。如果是远程通信,发送方是把加密后的数据发出去的,那么接收方势必要用原始的密钥key才能解密。那么接收方如何才能拿到这个密钥呢?有关这方面,可以参考《Core Java》卷二关于加密一章的讨论。——老外的书总是深入浅出,通过一个个例子&故事,引出一系列高深的专题。推荐TXs能够好好阅读几遍。


这里再给出一种简单的数据&密钥发送发生,也是很多项目采用的方法。即:

  • 假定有原始数据data,长度为len;
  • 生成长度为len的一串密钥key(比如前面示例给出的随机数);
  • 发送数据规定为2*len长度,前面len部分是data^key,后面len部分是key;
  • 接收方收到数据之后,就用后面len部分异或到前面len部分,最后的结果就是原始数据。


当然了,可能这个也比较简单。那么可以在此基础上进一步引入其他的算法,比如:

  • 增加一个字节,引入奇偶校验码;——参考《IMSI编码规则与奇偶校验算法
  • 将码流顺序按照一定的规律打乱,比如相邻的两个字节交换;
  • 等等


5. 参考资料

维基百科的异或加密介绍:http://zh.wikipedia.org/wiki/%E5%BC%82%E6%88%96%E5%8A%A0%E5%AF%86

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值