哈尔滨工程大学
实 验 报 告
实验名称: RC4加密
班 级:
学 号:
姓 名:
实验时间: 2015.6.15
成 绩:
指导教师:
实验室名称:
哈尔滨工程大学实验室与资产管理处制
一、实验名称
RC4加密
二、实验目的
通过编程实现RC4加密的算法设计,并加深对其的了解。
三、实验环境(实验所使用的器件、仪器设备名称及规格)
WindowXP系统计算机 ,Dev C++
四、实验任务及其要求
根据实验原理部分对RC4加密的介绍,自己创建明文信息,并选择一个密钥,编写RC4加密的实现程序,实现加密和解密操作。
五、实验设计(包括原理图、真值表、分析及简化过程、卡诺图、源代码等)
#include<stdio.h>
#include<string>
int main()
{
int n,i,j,tmp,t,x,m,p,c;
char M[256],C[256];
printf("请输入明文:");
gets(M);
printf("请输入主密钥长度:");
scanf("%d",&n);
c=1;
for(i=0;i<n;i++)
{
c*=2;}
int K[c],S[c],T[c];
printf("请输入主密钥:");
for(i=0;i<n;i++)
scanf("%d",&K[i]);
printf("请输入所需随机密钥长度:");
scanf("%d",&t);
for(i=0;i<c;i++)
S[i]=i;//对S初始化
for(i=0;i<c;i++)
{
T[i]=K[(i%n)];
printf("%d",T[i]);
}
printf("\n");//初始化T向量
j=0;
for(i=0;i<c;i++)
{
j=(j+S[i]+T[i])%c;
tmp=S[j];
S[j]=S[i];
S[i]=tmp;
}
for(i=0;i<c;i++)
printf("%d",S[i]);
printf("\n");//T对S进行初始置换
i=0;
j=0;
for(p=0;p<t;p++)
{i=(i+1)%c;
j=(j+S[i])%c;
tmp=S[j];
S[j]=S[i];
S[i]=tmp;
m=(S[i]+S[j])%c;
x=S[m];
C[p]=M[p]^x;
M[p]=C[p]^x;
}
printf("加密结果:");
for(p=0;p<t;p++)
printf("%c",C[p]);
printf("解密结果:");
for(p=0;p<t;p++)
printf("%c",M[p]);
六、实验步骤
RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特),在如今技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经不太可行,所以可以预见RC4的密钥范围任然可以在今后相当长的时间里抵御暴力搜索密钥的攻击。实际上,如今也没有找到对于128bit密钥长度的RC4加密算法的有效攻击方法。
程序实现时,需要注意的是,状态向量数组S和临时向量数组T的类型应设为unsigned char,而不是char。因为在一些机器下,将char默认做为signed char看待,在算法中计算下标i,j的时候,会涉及char转int,如果是signed的char,那么将char的8位拷贝到int的低8位后,还会根据char的符号为,在int的高位补0或1。由于密钥是随机产生的,如果遇到密钥的某个字节的高位为1的话,那么计算得到的数组下标为负数,就会越界。
七、实验过程与分析
八、实验结果总结
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加密算法的编译以及通过RC4对于密码的明文加密和密文解密的流程,并为以后的密码算法编程打好基础。更加熟悉的了解c语言环境的编程方式。
学生自评
注:根据自己所做实验情况,实事求是的给出“评定结果”和“实验成绩”,在相应等级的()内填入■。
第二篇:实验报告_密码学
《密码学与网络安全技术》课程上机报告
学 号:119074339
姓 名:许海龙
班 级:网112班
教 师:卫琳娜
安徽工业大学
2014年12月3日星期三
密码学实验
一、古典密码算法实验
一、 实验目的
通过编程实现替代密码算法和置换密码算法,加深对古典密码体制的了解,为深入学习密码学奠定基础。
二、 编译环境
运行 windows 或 linux 操作系统的 PC 机,具有 gcc(linux)、VC(windows)等 C语言编译环境。
三、 实验原理
古典密码算法历史上曾被广泛应用,大都比较简单,使用手工和机械操作来实现加密和解密。它的主要应用对象是文字信息,利用密码算法实现文字信息的加密和解密。下面介绍两种常见的具有代表性的古典密码算法,以帮助读者对密码算法建立一个初步的印象。
1. 替代密码
替代密码算法的原理是使用替代法进行加密,就是将明文中的字符用其它字符替代后形成密文。例如:明文字母 a、b、c、d ,用 D、E、F、G做对应替换后形成密文。
替代密码包括多种类型,如单表替代密码、多明码替代密码、多字母替代密码、多表替代密码等。下面我们介绍一种典型的单表替代密码,恺撒(caesar)密码,又叫循环移位密码。它的加密方法,就是将明文中的每个字母用此字符在字母表中后面第 k个字母替代。它的加密过程可以表示为下面的函数:
E(m)=(m+k) mod n
其中:m 为明文字母在字母表中的位置数;n 为字母表中的字母个数;k 为密钥;E(m)为密文字母在字母表中对应的位置数。 例如,对于明文字母 H,其在字母表中的位置数为 8,设 k=4,则按照上式计算出来的密文为 L:
E(8) = (m+k) mod n = (8+4) mod 26 = 12 = L
2. 置换密码
置换密码算法的原理是不改变明文字符,只将字符在明文中的排列顺序改变,从而实现明文信息的加密。置换密码有时又称为换位密码。
矩阵换位法是实现置换密码的一种常用方法。它将明文中的字母按照给的顺序安排在一个矩阵中,然后用根据密钥提供的顺序重新组合矩阵中字母,从而形成密文。例如,明文为 attack begins at five,密钥为 cipher,将明文按照每行 6 列的形式排在矩阵中,形成如下形式:
a t t a c k
b e g i n s
a t f i v e
根据密钥 cipher中各字母在字母表中出现的先后顺序,给定一个置换:
1 2 3 4 5 6
f =
1 4 5 3 2 6
根据上面的置换,将原有矩阵中的字母按照第 1 列,第 4 列,第 5 列,第 3 列,第 2列,第 6 列的顺序排列,则有下面形式:
a a c t t k
b i n g e s
a I v f t e
从而得到密文:abatgftetcnvaiikse
其解密的过程是根据密钥的字母数作为列数,将密文按照列、行的顺序写出,再根据由密钥给出的矩阵置换产生新的矩阵,从而恢复明文。
四、 实验内容和步骤
1、根据实验原理部分对替代密码算法的介绍,自己创建明文信息,并选择
一个密钥 k,编写替代密码算法的实现程序,实现加密和解密操作。
2、根据实验原理部分对置换密码算法的介绍,自己创建明文信息,并选择
一个密钥,编写置换密码算法的实现程序,实现加密和解密操作。
五、 总结与思考
记录程序调试过程中出现的问题,分析其原因并找出解决方法。记录最终实现的程序执行结果。
思考采取什么样的手段来防范类似对网络的攻击。
六、 实验结果
替换密码的加密解密
先是加密
实现程序为:
#include "stdio.h"
#include "conio.h"
main()
{
int k,i=0;
char a[100],b[100]={0};;
printf("please input your ming wen:\n");
gets(a);
printf("please input mi shi \n");
scanf("%d",&k);
printf("\n");
do{
b[i]=(char)(a[i]+k);
if(b[i]>122){
b[i]=(char)(b[i]-26);
}
i++;
}while(a[i]!='\0');
puts(b);
getch();
}
实验结果为:
再是解密:
实现程序为:
#include "stdio.h"
#include "conio.h"
main()
{
int k,i=0;
char a[100],b[100];
printf("please input mi wen: \n");
gets(a);
printf("please input mi shi: \n");
scanf("%d",&k);
printf("\n");
do{
b[i]=(char)(a[i]-k);
if(b[i]<97){
b[i]=(char)(b[i]+26);不知道三哪里的问题结果中的Y输不出来
}
i++;
}while(a[i]!='\0');
puts(b);
getch();
}
结果为:
置换密码
先是加密
实现程序
#include<stdio.h>
#define TRUE 1
#define FALSE 0
#define N 1000
#define M 50
int Glength(char *a)
{
char *pt;
int nlen=0;
pt=a;
while((*pt)!='\0')
{
nlen++;
pt++;
}
return nlen;
}
void encrypt(char *a,int n,int *b)
{
int i,j,k,t,x,y;
char c[M][M],d[M][M];
k=Glength(a);
puts(a);
t=k%n;
if(t==0)
{
x=k/n;
}
else
{
x=(k/n)+1;
}
printf("%d\n",x);
for(i=0;i<x;i++)
{
for(j=0;j<n;j++)
{
if(((a[i*n+j])>96)&&(a[i*n+j]<123))
{
c[i][j]=a[i*n+j];
printf("%c",c[i][j]);
}
else
{
c[i][j]=' ';
printf("%c",c[i][j]);
}
}
}
printf("\n hehe\n");
for(j=0;j<n;j++)
{
for(i=0;i<x;i++)
{
y=b[j];
printf("encrypt %d\t",y);
d[i][y]=c[i][j];
printf("--%c\t",d[i][y]);
}
}
printf("\n");
for(i=0;i<x;i++)
{
for(j=0;j<n;j++)
{
a[i*n+j]=d[i][j];
}
}
a[x*n+j+1]='\0';
puts(a);
}
void bubble_sort(char *a,int n,int *b)
{
int i,j,nTemp,k,x;
char change;
char c[N];
x=0;
strcpy(c,a);
for(i=n-1,change=TRUE;i>=1&&change;--i)
{
change=FALSE;
for(j=0;j<i;++j)
{
if(a[j]>a[j+1])
{
nTemp=a[j];
a[j]=a[j+1];
a[j+1]=nTemp;
change=TRUE;
}
}
}
i=0;
while((c[i])!='\0')
{
for(k=0;k<n;k++)
{
if((c[i])==a[k])
{
b[x]=k;
printf("%d\t",b[x]);
}
}
i++;
x++;
}
printf("\n");
puts(a);
}
int main()
{
int k;
char nArr[N],a[N];
int b[N];
clrscr();
printf("Please input key:\n");
gets(nArr);
k=Glength(nArr);
printf("Please input M word:\n");
gets(a);
printf("The data items in ascending order:\n");
bubble_sort(&nArr,k,&b);
puts(nArr);
encrypt(&a,k,&b);
puts(a);
printf("\n");
return 0;
}
加密结果为:
二、公钥加密算法—RSA
一、实验目的
通过使用 RSA 算法对实验数据进行加密和解密,掌握公钥加密算法的基本原理,熟练
掌握 RSA 算法各功能模块的工作原理和具体运算过程。
二、实验原理
RSA 公钥加密算法是 1977 年由 Ron Rivest、Adi Shamirh 和 LenAdleman 在(美国麻省理工学院)开发的。RSA 取名来自开发他们三者的名字。RSA 是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被 ISO 推荐为公钥数据加密标准。RSA 算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
1. RSA 的密钥生成
RSA 的算法涉及三个参数,n、e、d。
其中,n 是两个大质数 p、q 的积,n 的二进制表示时所占用的位数,就是所谓的密
钥长度。鉴于现代对于大整数分解的水平不断增强,一般 P、Q 的取值都要求在 1024
位以上。
e 和 d 是一对相关的值,e 可以任意取,但要求 e 与(p-1)*(q-1)互质;再选择 d,要求:
(e*d)mod((p-1)*(q-1))=1。
<n,e>、<n,d>就是密钥对。一般将前者当作公钥,后者作为私钥使用。
2. RSA 加密/解密过程
RSA 加解密和解密的算法完全相同,设 A 为明文,B 为密文,则:
A=B^e mod n;B=A^d mod n;
e 和 d 可以互换使用,即:
A=B^d mod n;B=A^e mod n;
三、实验环境
运行 Windows 或 Linux 操作系统的 PC 机,具有 gcc(Linux)、VC(Windows)等 C 语言编译环境。
四、实验内容和步骤
1. 根据本讲义提供的 RSA 程序,分析 RSA 算法的实现过程:
(1)、利用:void GenerateKey(RSA_Key& PublicKey,RSA_Key& PrivateKey,unsigned int
iKeySize)函数根据实际需要生成符合要求长度的公钥和私钥,大致步骤如下:
a) 随机生成两个指定长度的大素数 P,Q。
b) 计算 N=P*Q,以及 N 的欧拉函数 φ(N)=(P-1)*(Q-1)。
c) 随机生成一个与 φ(N)互素的大整数 E(公钥)。
d) 根据公式 ed≡1(modΦ(N)),利用函数 multi_inverse(1, Big*, Big, Big*)计算出
私钥 D。
(2)、将某个大整数赋值给一个 Big 型变量 M(明文)。
(3)、调用函数 powmod(..,..,..,..)对明文 M 加密得到密文 C。
(4)、调用函数 powmod(..,..,..,..)对密文 C 解密得到明文 D。
(5)、比较 M 与 D 是否一致,判断实验结果是否正确。
(6)、调换公钥、私钥后重复以上步骤,验证 e、d 的可互换性,并思考为什么可以这样
做。
2. 使用实例分析
取 p=11,q=13。
首先计算:
n=pq=11×13=143
φ(n)=(p-1)(q-1)=(11-1) ×(13-1)=120
然后选择 e=17,满足 gcd(e,φ(n))=gcd(17,120)=1,然后根据 ed≡1(modφ(N))计算 d=113。
则:公钥:<17,143>、私钥:<113, 143>。
设明文信息:m=24。对明文信息加密,得密文为:
c≡m^e % N=24^17%143=7
密文 c 经过公开信道发送到接收方后,接收方用私钥 d 对密文进行解密:
m≡c^d % N=7^113%143=24
从而正确地恢复出明文。
五、思考题
1、阐明 RSA 密钥生成以及加密、解密流程
(1)RSA密钥生成:1)找出p,q,r三个数,p,q互质,r与(p-1)(q-1)互质,p,q,r这三个数便是private key。
2)找出m,使得mr==1 mod (p-1)(q-1)
3)计算n=pq,m,n这两个数便是public key
(2)流程:用户A用B的公钥对key进行加密,B收到消息后用自己的私钥进行解密获取key。
2. 使用提供的模块编写 RSA 加密程序对数据进行加密和解密,提交程序代码和执行结果。
程序代码:
#include "time.h"
#include "big.h"
#include <iostream>
#define BUFFERSIZE 4096
static miracl* mip = mirsys ( BUFFERSIZE, 0 );
struct RSA_Key//密钥结构体
{
Big e;
Big N;
};
int main(void)
{
void GenerateKey(RSA_Key& PublicKey,RSA_Key& PrivateKey,unsigned int iKeySize);//密钥生成函数
RSA_Key PublicKey;//公钥 <e,N>
RSA_Key PrivateKey;//私钥 <d,N>
Big M;//明文M
Big C;//密文C
Big D;//解密文D
unsigned int iKeySize;
std::cout<<"请输入加密密钥长度(单位比特)"<<std::endl;
std::cin>>iKeySize;
std::cout<<"密钥生成中......"<<std::endl;
GenerateKey(PublicKey,PrivateKey,iKeySize/4);//产生iKeySize bit密钥
std::cout<<"密钥生成完毕"<<std::endl;
std::cout<<"请输入明文:"<<std::endl;
std::cin>>std::hex>>M;
powmod(M.getbig(), PublicKey.e.getbig(), PublicKey.N.getbig(), C.getbig());//调用加密函数计算:C=(M^e)%N
std::cout<<"RSA加密密文:"<<std::endl;
std::cout<<std::hex<<C<<std::endl;
powmod(C.getbig(), PrivateKey.e.getbig(), PrivateKey.N.getbig(), D.getbig());//解密与加密使用同一函数,只是密钥不同即:D=(C^d)%N
std::cout<<"解密:"<<std::endl;
std::cout<<std::hex<<D<<std::endl;//若D与M相同,可认为正确
system("Pause");
return 0;
}
void GenerateKey(RSA_Key& PublicKey,RSA_Key& PrivateKey,unsigned int iKeySize)
{
void GeneratePrime(Big* bigGenPrime,int iLength, int iBase);
unsigned int InitRandom();
unsigned int RAND_SEED = InitRandom();
irand(RAND_SEED);
mip->IOBASE = 16;
set_io_buffer_size( BUFFERSIZE);
Big E,D,P,Q,N,Z;
GeneratePrime(&P, iKeySize /4, 16);//生成强素数P
GeneratePrime(&Q, iKeySize /4, 16);//生成强素数Q
N =P *Q;//计算N
Z = (P-1) * (Q-1);//计算N的欧拉函数
do
{
GeneratePrime(&D, iKeySize /4, 16);
}while(Z % D == 0);//反复生成素数,直到该素数与Z互素,得到密钥D
multi_inverse(1, &D, Z, &E); // 根据公式ed mod z = 1 计算E
PublicKey.e=E;
PublicKey.N=N;
PrivateKey.e=D;
PrivateKey.N=N;
return;
}
void GeneratePrime(Big* bigGenPrime,int iLength, int iBase)
{
*bigGenPrime = 4; // 任取非素数
set_io_buffer_size(50000);
while (!isprime(bigGenPrime->getbig()))//若非素数则:
{
bigdig (iLength,iBase,bigGenPrime->getbig());//重新生成
}
return;
}
unsigned int InitRandom()//随机数生成函数
{
__time64_t long_time;
srand((unsigned)time(&long_time));
unsigned int RAND_SEED=rand();
return RAND_SEED;
}