您的位置:首页 > 编程语言

7行核心代码对任何数据进行军事级别的加密或解密

2016-03-06 20:19 411 查看
TEA(Tiny Encryption Algorithm)算法是一种对称的Feistel加密结构的分组加密算法。由于理想分组加密在实践中的种种困难。Feistel最先提出使用乘积加密的概念来逼近理想的分组加密。乘积加密是指依次使用两个或两个以上基本密码,所得结果的密码强度将强于所有单个密码的强度。这种方法的本质是开发一个分组加密,密钥长为k位,分组长为n位,采用2^k个变换,而不是理想分组密码的(2^n)!个可用变换。

Feistel建议交替地使用代替和置换。代替和置换的定义如下所述。

代替:每个明文元素或元素组被唯一地替换为相应的密文元素或元素组。
置换:明文元素的序列被替换为该序列的一个置换。也就是说,序列里没有元素被添加、删除或替换,但序列里元素出现的顺序改变了。

混淆和扩散

实际上,这是Claude Shannon提出的交替使用混淆扩散的乘积加密的实际应用。Shannon引进混淆和扩散这两个术语来刻画任何加密系统的两个基本构件。他关注的是如何挫败基于统计方法的密码分析。他假设攻击者拥有明文统计特征的知识。例如某种人类语言的可读信息,其不同字母的频率分布是已知的。或者已知信息中极有可能出现某些单词或短语。如果这些特征以任何形式体现在密文中,密码分析者就有可能推导出密钥或其一部分,至少是包含确切密钥的一个密钥集,在Shannon所指的强理想加密中,密文所有的统计特征都是独立于所用密钥的。任意替代加密即理想分组加密,就是这样一种加密,不过它是不可能获得实际应用的。

舍弃对理想系统的追求,Shannon建议了两种对付统计分析的方法:扩散和混淆。扩散就是指使明文的统计特性消散在秘闻中,这可以通过让每个明文数字尽可能地影响多个密文数字获得,等价于说每个密文数字被许多个明文数字影响。扩散的方法是尽可能地使明文和密文间的统计关系变得复杂,以挫败推导出密钥的企图。另一方面,混淆则是尽可能使密文和加密密钥之间的统计关系变得更加复杂,以阻止攻击者发现密钥。

下图描述了Feistel提出的结构。加密算法的输入是长为2w位的明文分组和密钥K。明文分组被分为等长的两部分:L0和R0.这两半数据经过n轮迭代后组合成密文分组。第i轮迭代的输入Li-1和Ri-1来自于上轮迭代的输出;而输入的子密钥Ki是由整个密钥K推导出的。Ki一般不同于K,也互不相同。每轮迭代都有相同的结构。代替作用在数据的左半部分。它通过用轮函数F作用于数据的右半部份后,与左半部分数据进行异或来完成。每轮迭代的轮函数是相同的,但是输入的子密钥Ki不同。换一句话说,F是w位长的右半分组以及y位长的子密钥的函数,输出w位的值:F(REi,Ki+1)。替代之后,交换数据的左右两半换成置换。这种结构是Shannon提出的代替置换网络(SPN,Substitution-Permutation
Network)的一种特别形式。

Feistel结构的具体实现依赖于以下参数和特征。

分组长度:分组越长意味着安全性越高(其他数据不变),但是会降低加、解密的速度。这种安全性的增加来自于更加的扩散性。
密钥长度:密钥较长同样意味着安全性较高,但会降低加、解密速度。这种安全性的增加来自于更好的抗穷尽攻击能力和更好的混淆性。
迭代轮数:Feistel密码的本质在于单轮不能提供足够的安全性而多轮加密可取得很高的安全性。
子密钥产生算法:子密钥产生越复杂,密码分析就越困难。
轮函数F:同样,轮函数越复杂,抗攻击的能力就越强。

设计Feistel加密还有两个其他方面的考虑。

快速软件加/解密:许多情况下,加密算法被嵌入到应用程序中,以避免硬件实现的麻烦。因此,算法执行速度很重要。
简化分析难度:尽管我们喜欢把算法设计得使密码分析尽可能困难,然而将算法设计得容易分析也有它的好处。如果算法描述起来简洁清楚,那么分析其脆弱性也就容易些,因而可以开发出更强的算法。

解密

Feistel密文的解密过程本质上与加密过程一致,其规则如下:将密文作为算法的输入,但是逆序使用子密钥Ki。也就是说,第一轮使用Kn,第二轮使用Kn-1,直到最后一轮使用K1。这是一个很好的特性,因为我们不需要分别实现加密和解密两个算法。



TEA算法

TEA算法运用模加和模减代替了Feistel加密结构里的异或,极其有利于软件的实现。 它由剑桥大学计算机实验室的David Wheeler和Roger Needham设计,最先于1994年在鲁汶快速软件加密研讨会上亮相,并于研讨会中发表。这个加密算法不受任何专利保护。

属性

TEA在32比特的无符号整数上操作(可从64位的数据得到)并使用128比特的密钥。它迭代64轮,两轮一个周期。其子密钥的产生方法极其简单。人们用各种各样的神奇常数来防止基于轮对称的简单攻击。这个神奇的常数一般是2654435769(0x9E3779B916),即2^32/黄金分割率。

TEA有几个弱点。它的四个密钥是等价的——每一个密钥等价于其他三个,这就导致密钥的有效长度仅为126比特。TEA在作为加密哈希函数的时候就特别糟糕。黑客就利用了这个弱点攻击了微软的Xbox游戏控制台。Xbox就是用TEA加密算法作为哈希函数。TEA也容易被相关密钥攻击破解。因为这些弱点,XTEA加密算法被开发了出来。



XTEA

在密码学上,XTEA(eXtened TEA)是一个分组加密算法,克服了TEA的弱点。它也是由David Wheeler和Roger Needham设计的,最先出现在1997年的一份未发表的技术报告上。它也不受任何专利保护。

类似于TEA,XTEA也是一个64位的分组加密算法,密钥是128比特,轮数是人们推荐的64轮。它与TEA有几个明显的区别,包括更加复杂的密钥编排和移位、异或的重新组织等等。



XTEA的强度

128位的密钥共有2^128种可能,利用穷举攻击的方法,假设每微秒执行一次解密,平均需要5.3*10^21年才能破解,假设每微秒执行1000万次解密,平均需要5.3*10^17年才能破解。差分密码分析的效率不高于穷举攻击。

XTEA的C语言代码实现(VS2015环境下)

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define num_rounds 32
#define MAX_PASSWORD 100
void encipher(unsigned int v[2], unsigned int key[4]);
void decipher(unsigned int v[2], unsigned int key[4]);
int main(int argc, char* argv[]) {
	FILE *fpin, *fpout;
	uint32_t msg[2];
	char password[MAX_PASSWORD] = { 0 };  // = {0}很重要,否则如果你的密码过短,会导致系统自动用乱码补齐你的密码。
	if (argc != 5) {
		printf("\nUsage: %s e(encipher) password sourceFileName outFileName", argv[0]); //提示用户如何使用该程序
		printf("\nUsage: %s d(decipher) password sourceFileName outFileName", argv[0]);
		return 0;
	}
	strcpy_s(password, MAX_PASSWORD, argv[2]);  //拷贝密码
	if (!fopen_s(&fpin, argv[3], "rb") && !fopen_s(&fpout, argv[4], "wb")) {  //如果打开文件失败就退出程序
		if (argv[1][0] == 'e') {
			while (!feof(fpin)) {  //读到文件结尾就结束循环
				msg[0] = msg[1] = 0;   //=0很重要 否则就会导致加密失败。
				if (fread(msg, 1, 8, fpin) == 0) {  //读不到数据也退出循环
					break;
				}
				encipher(msg, (unsigned int*)password);
				fwrite(msg, 1, 8, fpout);
			}
		}
		else if (argv[1][0] == 'd') {
			while (!feof(fpin)) {
				msg[0] = msg[1] = 0;
				if (fread(msg, 1, 8, fpin) == 0) {
					break;
				}
				decipher(msg, (unsigned int*)password);
				fwrite(msg, 1, 8, fpout);
			}
		}
		else {  //加密解密命令错误也退出程序
			puts("Illegal command!");  
		}
	}
	else {
		printf("\nFail to open files.");
	}
	fclose(fpin);
	fclose(fpout);
	return 0;
}
/*使用128位的密钥加密或解密文件,一次操作64比特数据*/
void encipher(uint32_t v[2], uint32_t key[4]) {
	uint32_t i;
	uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
	for (i = 0; i < num_rounds; i++) {
		v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
		sum += delta;
		v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
	}
	v[0] = v0; v[1] = v1;
}
void decipher(uint32_t v[2], uint32_t key[4]) {
	uint32_t i;
	uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta*num_rounds;
	for (i = 0; i < num_rounds; i++) {
		v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
		sum -= delta;
		v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
	}
	v[0] = v0; v[1] = v1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: