流密码与分组密码编程.docx
- 文档编号:30367206
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:11
- 大小:29.23KB
流密码与分组密码编程.docx
《流密码与分组密码编程.docx》由会员分享,可在线阅读,更多相关《流密码与分组密码编程.docx(11页珍藏版)》请在冰豆网上搜索。
流密码与分组密码编程
流密码与分组密码编程
上机一:
流密码与分组密码编程
【上机目的】
熟悉流密码和分组密码加密/解密算法的基本原理,通过编程/开源代码分析分别了解一种标准流密码算法和一种标准分组密码算法的运行原理。
【上机环境】
1、硬件PC机一台。
2、系统配置:
操作系统windowsXP以上。
3、编程语言:
C/C++/C#/Java/Python
【上机内容及要求】
1、分别利用RC4算法(或其它任一种标准流密码算法)和DES算法(或AES算法等其它任一种标准分组密码算法)对数据进行加解密操作
2、代码分析及注释
3、代码调试
4、代码修改及测试(选做)
备注:
可借鉴网上相关算法的开源代码进行编程实现,编程语言不限。
【上机报告】
1、提交关键功能有注释的源码。
2、提交运行测试结果(运行截图及说明)。
3、运行测试结果分析。
4、上机总结(任务完成情况、出现或待解决的问题、收获、体会等)。
流密码
流密码就是使用较短的一串数字(叫它密钥吧),来生成无限长的伪随机密码流,当然事实上只需要生成和明文长度一样的密码流就够了。
一个非常简单的流密码算法是,用6个比特位101100做密钥,将它不断重复得到密码流101100101100101100....直到和明文长度相等,然后将密码流和明文“相加”就得到密文了,解密就是将这个密码流和密文“相加”。
流密码算法有个特殊的名称——维吉尼亚密码,当然这里密钥长度可以不是6。
用较短的密钥产生无限长的密码流的方法非常多,其中有一种就叫做RC4。
把明文的信息限制在ascii码字符集内(它已经能表示所有的英文资料了哈哈),每个字符是一个比特,占8位。
假设明文是abc,a、b、c的ascii值分别为97、98、99。
二进制形式为01100001、01100010、01100011。
密钥流和明文长度一样,假设是sdf,同样可以得到二进制流01110011、01100100、01100110,让他们在对应位做异或运算就可以得到密文了,c语言有^运算符来实现“相加”的操作。
我们就直接对字符进行“相加”即a^s,b^d,c^f。
得到的结果的二进制形式为00010010、00000110、00000101,它们分别表示ascii码值为18、6、5的字符
RC4用两步来生成密码流
首先你指定一个短的密码,储存在key[MAX]数组里,还有一个数组S[256],令S[i]=i。
然后利用数组key来对数组S做一个置换,也就是对S数组里的数重新排列,排列算法为
forifrom0to255
S[i]:
=i
endfor
j:
=0
forifrom0to255
j:
=(j+S[i]+key[imodkeylength])mod256
swapvaluesofS[i]andS[j]
endfor
第二步利用上面重新排列的数组S来产生任意长度的密钥流,算法为
i:
=0
j:
=0
whileGeneratingOutput:
i:
=(i+1)mod256
j:
=(j+S[i])mod256
swapvaluesofS[i]andS[j]
K:
=S[(S[i]+S[j])mod256]
outputK
endwhile
outputK一次产生一字符长度(8bit)的密钥流数据,一直循环直到密码流和明文长度一样为止。
产生密钥流之后,对信息进行加密和解密就只是做个“相加”的运算。
RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特),在如今技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经不太可行,所以可以预见RC4的密钥范围任然可以在今后相当长的时间里抵御暴力搜索密钥的攻击。
实际上,如今也没有找到对于128bit密钥长度的RC4加密算法的有效攻击方法。
在介绍RC4算法原理之前,先看看算法中的几个关键变量:
1、密钥流:
RC4算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是500字节,那么密钥流也是500字节。
当然,加密生成的密文也是500字节,因为密文第i字节=明文第i字节^密钥流第i字节;
2、状态向量S:
长度为256,S[0],S[1].....S[255]。
每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换;
3、临时向量T:
长度也为256,每个单元也是一个字节。
如果密钥的长度是256字节,就直接把密钥的值赋给T,否则,轮转地将密钥的每个字节赋给T;
4、密钥K:
长度为1-256字节,注意密钥的长度keylen与明文长度、钥流的长度没有必然关系,通常密钥的长度趣味16字节(128比特)。
RC4的原理分为三步:
1、初始化S和T
fori=0to255do
S[i]=i;
T[i]=K[imodkeylen];
2、初始排列S
fori=0to255do
j=(j+S[i]+T[i])mod256;
swap(S[i],S[j]);
3、产生密钥流
forr=0tolendo//r为明文长度,r字节
i=(i+1)mod256;
j=(j+S[i])mod256;
swap(S[i],S[j]);
t=(S[i]+S[j])mod256;
k[r]=S[t];
下面给出RC4加密解密的C++实现:
加密类:
/*
加密类
*/
classRC4{
public:
/*
构造函数,参数为密钥长度
*/
RC4(intkl):
keylen(kl){
srand((unsigned)time(NULL));
for(inti=0;i inttmp=rand()%256; K.push_back(char(tmp)); } } /* 由明文产生密文 */ voidencryption(conststring&,conststring&,conststring&); private: unsignedcharS[256];//状态向量,共256字节 unsignedcharT[256];//临时向量,共256字节 intkeylen;//密钥长度,keylen个字节,取值范围为1-256 vector vector /* 初始化状态向量S和临时向量T,供keyStream方法调用 */ voidinitial(){ for(inti=0;i<256;++i){ S[i]=i; T[i]=K[i%keylen]; } } /* 初始排列状态向量S,供keyStream方法调用 */ voidrangeS(){ intj=0; for(inti=0;i<256;++i){ j=(j+S[i]+T[i])%256; //cout<<"j="< S[i]=S[i]+S[j]; S[j]=S[i]-S[j]; S[i]=S[i]-S[j]; } } /* 生成密钥流 len: 明文为len个字节 */ voidkeyStream(intlen); }; voidRC4: : keyStream(intlen){ initial(); rangeS(); inti=0,j=0,t; while(len--){ i=(i+1)%256; j=(j+S[i])%256; S[i]=S[i]+S[j]; S[j]=S[i]-S[j]; S[i]=S[i]-S[j]; t=(S[i]+S[j])%256; k.push_back(S[t]); } } voidRC4: : encryption(conststring&plaintext,conststring&ks,conststring&ciphertext){ ifstreamin; ofstreamout,outks; in.open(plaintext); //获取输入流的长度 in.seekg(0,ios: : end); intlenFile=in.tellg(); in.seekg(0,ios: : beg); /生产密钥流 keyStream(lenFile); outks.open(ks); for(inti=0;i outks<<(k[i]); } outks.close(); //明文内容读入bits中 unsignedchar*bits=newunsignedchar[lenFile]; in.read((char*)bits,lenFile); in.close(); out.open(ciphertext); //将明文按字节依次与密钥流异或后输出到密文文件中 for(inti=0;i out<<(unsignedchar)(bits[i]^k[i]); } pre">out.close(); delete[]bits; } 解密类: /* 解密类 */ classRC4_decryption{ public: /* 构造函数,参数为密钥流文件和密文文件 */ RC4_decryption(conststringks,conststringct): keystream(ks),ciphertext(ct){} /* 解密方法,参数为解密文件名 voiddecryption(conststring&); private: stringciphertext,keystream; }; voidRC4_decryption: : decryption(conststring&res){ ifstreaminks,incp; ofstreamout inks.open(keystream); incp.open(ciphertext); //计算密文长度 inks.seekg(0,ios: : end); constintlenFile=inks.tellg(); inks.seekg(0,ios: : beg); //读入密钥流 unsignedchar*bitKey=newunsignedchar[lenFile]; inks.read((char*)bitKey,lenFile); inks.close(); //读入密文 unsignedchar*bitCip=newunsignedchar[lenFile]; incp.read((char*)bitCip,lenFile); incp.close(); //解密后结果输出到解密文件 out.open(res); for(inti=0;i out<<(unsignedchar)(bitKey[i]^bitCip[i]); out.close(); } 程序实现时,需要注意的是,状态向量数组S和临时向量数组T的类型应设为unsignedchar,而不是char。 因为在一些机器下,将char默认做为signedchar看待,在算法中计算下标i,j的时候,会涉及char转int,如果是signed的char,那么将char的8位拷贝到int的低8位后,还会根据char的符号为,在int的高位补0或1。 由于密钥是随机产生的,如果遇到密钥的某个字节的高位为1的话,那么计算得到的数组下标为负数,就会越界。 程序运行示例 main函数: intmain(){ RC4rc4(16);//密钥长16字节 rc4.encryption("明文.txt","密钥流.txt","密文.txt"); RC4_decryptiondecrypt("密钥流.txt","密文.txt"); decrypt.decryption("解密文件.txt"); } 明文: 我爱卜俊杰! 密文: '柀L&t餥6洲 密钥流: 镈膺嚬3屽u 解密文件: 我爱卜俊杰! 验证成功 实验心得与困难: c代码,编译得到encrypt可执行文件,在命令行下运行encrypt命令(后面必须跟一个纯文本文件名FILE作为参数),然后输入密钥,可将文件FILE进行加密,再次运行并输入相同的密钥可以进行解密,如果前后密钥不同,就不是解密而是进行二次加密了,哈我可以用自己理解的方式来加密信息了: )这个程序本是针对纯英文文件来加密的,但是文件里有中文时一样可以加解密。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 密码 分组 编程