RSA和DES算法实现实验
一、实验角色
我是第十一小组的一位组员。我的任务是实现RSA和DES算法,并且提供加密和解密的接口,也就是说,能够对明文进行加密,对密文进行解密。我的主要工作是写一个类库,用户可以通过该类库提供的接口调用该类库中的函数,从而实现对数据的加密操作和解密操作。
二、实验要求
实现RSA算法的加密和解密。
实现DES算法的加密和解密。
三、实验原理
RSA算法(公开密钥算法)的原理:
RSA算法基于数论中的一些问题。我在这里只是简要的说明如何使用该方法,有关详细的信息请参考相关的资料。
1. 选择两个大的素数p和q(典型情况下为1024位)
2. 计算n = p * q 和 z =(p-1)*(q-1).
3. 选择一个与z互素的数,将它称为d
4. 找到e,使其满足e*d = 1 mod z
提前计算出这些参数以后,我们就可以开始执行加密了。首先将明文分成块,使得每个明文消息P落在间隔0*P<n中。为了做到这一点,只要将明文划分成k位的块即可,这里k是满足2^k<n的最大整数。
为了加密一个消息P,只要计算C=P^e(mod n) 即可。为了解密C,只要计算P=C^d(mod n)即可。可以证明,对于指定范围内的所有P,加密盒解密互为反函数。为了执行加密,你需要e和n;为了执行解密,你需要d和n。因此,公钥是有(e,n)对组成,而私钥是有(d,n)对组成。
RSA算法的安全性建立在分解大数的困难基础之上。RSA加密解密算法的要点如下:
1. 密钥是成对产生的。
2. 加密密钥不能用来解密。
3. 加密密钥和算法是公开的,解密密钥是保密的。
4. 从加密密钥推出解密密钥十分困难。
RSA算法的模型:
加密和解密算法举例:
选择p = 3 ,q = 11,则,n = p * q = 33 ,z = (p – 1)*(q – 1)= 20,因为7 与
20 互质,所以选择d = 7,选择e = 3 ,使得d * e = 1(mod 20),即计算密文C = P^3(mod 33),加密密钥为(3,33);计算明文P = C^7 (mod 33),解密密钥为(7,33)。
P = 2^k < 33,k = 5 ,即用5 bit 表示一个信息,有32 种表示。
分别用其中1——26表示A——Z 26个字母,如明文为SUZANNE,密文就为
19 21 26 01 14 14 05。
DES算法(对称密钥算法)的原理:
在介绍DES数据加密算法之前,先介绍一下DES算法中需要用到的两种硬件设备:
P盒与S盒。P盒效果相当于对一个8位输入实现一个转置操作。S盒的效果相当于对一个3位的输入实现一个置换操作。
当我们将一系列这样的S盒与P盒叠加起来构成乘积密码是,这些基本元素的威力就会发挥出来。
DES(Data Encryption Standard)数据加密算法,在工业界广泛应用于安全产品中。
DES的基本结构如下左图所示:
明文按64位数据块的单元被加密,生成64位密文。DES算法带有一个56位密钥作为参数,它共有19个步骤。第一步是一个与密钥无关的转置操作,它直接作用在64位明文上。最后一步正好是这个转置操作的逆操作。最后一步之前的那个步骤是交换左32位和右32位。剩下的16步在功能上是完全相同的,但使用了原始密钥的不同函数作为参数。DES算法的设计允许使用同样的密钥来完成加密和解密过程。在DES算法中,解密的步骤只是解密步骤地相反顺序而已。这些中间步骤的操作情况如下右图所示。每个步骤接受2个32位输入,并产生两个32位输出。左边的输出只是右边输入的一份副本而已。右边的输出是左边输入与一个函数值逐位异或的结果,该函数的输入参数是右边的输入和当前步骤地密钥Ki。所有的复杂性都在这个函数种。
此函数包含4个顺序执行的步骤。第一步,根据一个固定的转置和复制规则,将32位Ri-1扩展成一个48位的数字E。第二步,E和Ki被异或在一起。然后,异或的结果被分成8个6位组,每个6位组被输入到不同的S盒中。对于每个S盒,共有64种可能的输入,每种输入被映射到一个4位输出上。最后,将这8*4位通过一个P盒。
四、实验步骤与程序:
鉴于我写的是一个类库,对用户提供调用的接口,而把实现封装起来,用户只要根据他的需要调用相应的函数,而不用关心具体的实现细节。至于实验的步骤,由于只是一个类库,用户只要调用他感兴趣的函数就可以了,具体的步骤由用户自己决定,我只是提供一些方法而已。
RSA类库的源代码:
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
class RSAExchange
{
private RSAParameters publicKey; //公钥
private RSAParameters privateKey; //私钥
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
public void setPublicKey() //设置公钥
{
publicKey = RSA.ExportParameters(false);
}
public void setPrivateKey() //设置私钥
{
privateKey = RSA.ExportParameters(true);
}
public RSAParameters getPublicKey() //返回RSAParameters类型的公钥
{
return publicKey;
}
public RSAParameters getPrivateKey() //返回RSAParameters类型的私钥
{
return privateKey;
}
public string getPublicKeyXml() //返回string类型的公钥
{
return RSA.ToXmlString(false);
}
public string getPrivateKeyXml() //返回string类型的私钥
{
return RSA.ToXmlString(true);
}
public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{ // 对 byte 型的数据用公钥进行加密,公钥类型RSAParameters
// byte [] DataToEncrypt 明文
// RSAParameters RSAKeyInfo 公钥
try
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSA.ImportParameters(RSAKeyInfo);
return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
}
catch(CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
}
public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo,bool DoOAEPPadding)
{ //对 byte 型的数据用私钥进行解密 ,私钥类型 RSAParameters
//byte [] DataToDecrypt 密文
//RSAParameters RSAKeyInfo 私钥
try
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSA.ImportParameters(RSAKeyInfo);
return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
catch(CryptographicException e)
{
Console.WriteLine(e.ToString());
return null;
}
}
public byte[] EncryptDataWithPublicKey(byte[] dataToEncrypt,string publicKey)
{ // 对 byte 型的数据用公钥进行加密,公钥类型 string
// byte [] DataToEncrypt 明文
//string publicKey 公钥
RSAExchange re = new RSAExchange();
re.RSA.FromXmlString(publicKey);
re.setPublicKey();
byte[] encryptedData;
encryptedData = re.RSAEncrypt(dataToEncrypt,re.getPublicKey(),false);
return encryptedData;
}
public byte[] DecryptDataWithPrivateKey(byte[] dataToDecrypt,string privateKey)
{ //对 byte 型的数据用私钥进行解密 ,私钥类型 string
//byte [] DataToDecrypt 密文
//string privateKey 私钥
RSAExchange re = new RSAExchange();
re.RSA.FromXmlString(privateKey);
re.setPrivateKey();
byte[] decrypteData;
decrypteData = re.RSADecrypt(dataToDecrypt,re.getPrivateKey(),false);
return decrypteData;
}
DES类库的源代码:
class DESExchange
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] DESKey;
byte[] DESIV;
public ICryptoTransform getEncryptor()
{
return des.CreateEncryptor();
}
public ICryptoTransform getDecryptor()
{
return des.CreateDecryptor();
}
public void setKey() //设置DES密钥
{
des.GenerateKey();
DESKey = des.Key;
}
public void setIV() //设置位移矢量
{
des.GenerateIV();
DESIV = des.IV;
}
public byte[] getDESKey() //返回 byte [] 型的 DES密钥
{
return DESKey;
}
public byte[] getDESIV() //返回 byte [] 型的 位移矢量
{
return DESIV;
}
public string getDESKeyStr() //返回 string 类型的 DES密钥
{
UnicodeEncoding ByteConverter = new UnicodeEncoding();
return ByteConverter.GetString(DESKey);
}
public string getDESIVStr() //返回 string 类型的 位移矢量
{
UnicodeEncoding ByteConverter = new UnicodeEncoding();
return ByteConverter.GetString(DESIV);
}
public byte[] EncryptData(byte[] dataToEncrypt,byte[] desKey,byte[] desIV)
{ //用DES密钥和位移矢量对数据进行加密
//被加密的数据类型 byte []
//DES密钥类型 byte []
//位移矢量类型 byte []
ICryptoTransform transformer = des.CreateEncryptor(desKey,desIV);
byte[] result ;
result = transformer.TransformFinalBlock(dataToEncrypt,0,dataToEncrypt.Length);
return result;
}
public byte[] EncryDataWithKeyIv(byte [] dataToEncrypt,string deskey,string desiv)
{ //用DES密钥和位移矢量对数据进行加密
//被加密的数据类型 byte []
//DES密钥类型 string
//位移矢量类型 string
UnicodeEncoding ByteConverter = new UnicodeEncoding();
byte [] DESkey = ByteConverter.GetBytes(deskey);
byte [] DESiv = ByteConverter.GetBytes(desiv);
byte [] result;
result = EncryptData(dataToEncrypt,DESkey,DESiv);
return result;
}
public byte[] DecryptData(byte[] dataToDecrypt,byte[] desKey,byte[] desIV)
{ //用DES密钥和位移矢量对数据进行解密
//被解密的数据类型 byte []
//DES密钥类型 byte []
//位移矢量类型 byte []
ICryptoTransform transformer = des.CreateDecryptor(desKey,desIV);
byte[] result ;
result = transformer.TransformFinalBlock(dataToDecrypt,0,dataToDecrypt.Length);
return result ;
}
public byte[] DecryptDataWithKeyIv(byte[] dataToDecrypt,string deskey,string desiv)
{ //用DES密钥和位移矢量对数据进行解密
//被解密的数据类型 byte []
//DES密钥类型 string
//位移矢量类型 string
UnicodeEncoding ByteConverter = new UnicodeEncoding();
byte [] DESkey = ByteConverter.GetBytes(deskey);
byte [] DESiv = ByteConverter.GetBytes(desiv);
byte [] result;
result = DecryptData(dataToDecrypt,DESkey,DESiv);
return result;
}
public static void EncryptData(String inName, String outName, byte[] desKey, byte[] desIV)
{ //对 inName 文件中的数据用DES密钥和位移矢量进行加密,把加密后的密文存放在 //文件 outName 中
FileStream fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
FileStream fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write);
fout.SetLength(0);
byte[] bin = new byte[100];
long rdlen = 0;
long totlen = fin.Length;
int len;
DES des = new DESCryptoServiceProvider();
CryptoStream encStream = new CryptoStream(fout, des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write);
Console.WriteLine("Encrypting...");
while(rdlen < totlen)
{
len = fin.Read(bin, 0, 100);
encStream.Write(bin, 0, len);
rdlen = rdlen + len;
Console.WriteLine("{0} bytes processed", rdlen);
}
encStream.Close();
fout.Close();
fin.Close();
}
public static void DecryptData(String inName, String outName, byte[] desKey, byte[] desIV)
{ //对 inName 文件中的数据用DES密钥和位移矢量进行解密,把加密后的密文存放在
//文件 outName 中
FileStream fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
FileStream fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write);
fout.SetLength(0);
byte[] bin = new byte[100];
long rdlen = 0;
long totlen = fin.Length;
int len;
DES des = new DESCryptoServiceProvider();
CryptoStream encStream = new CryptoStream(fout, des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Write);
Console.WriteLine("Encrypting...");
while(rdlen < totlen)
{
len = fin.Read(bin, 0, 100);
encStream.Write(bin, 0, len);
rdlen = rdlen + len;
Console.WriteLine("{0} bytes processed", rdlen);
}
encStream.Close();
fout.Close();
fin.Close();
}
五、思考题
1. RSA算法适不适合对大量的数据进行加密?DES算法呢?
2. RSA和DES的加密速度哪一个跟快一点?
3. RSA和DES的可靠性如何?
六、个人日志
见5020339157 朱刚的个人日志文件
七、文档
见组文档
八、参考文献
1. William Stallings 著
《密码编码学与网络安全:原理与实践》 第二版
电子工业出版社 2001年4月
2. Andrew S.Tanenbaum 著
《计算机网络 第四版 》
清华大学出版社 2004 年8 月
3.Charles Wright 著
《C#编程技术与技巧》
机械工业出版社 2002 年 9 月
4.Peter Thorsteinson & G.Gnana Arun Ganesh 著
《.NET安全性与密码术》
清华大学出版社 2004 年 8 月
九、开发小结:
这次的网络大作业是我参与的第一个大型的软件开发项目,也是第一次和其他同学合作一起开发一个软件。虽然是初次合作,也没有什么软件开发的经验,但我感觉到我们的开发团队非常的团结,每个人都很有团队合作的精神,互相帮助,有什么问题都能够一起讨论,不管是一开始的软件设计阶段,还是后来的编码和调试阶段,大家的心都很齐,碰到了什么技术问题,或是其他的在编程过程中出现的问题,大伙都群策群力,集思广益,热烈的讨论最佳的解决方法,在整个的开发开发过程中,克服了一个又一个技术难关,最终完成了整个系统的设计,开发,调试。虽然最后做出来的软件还略显粗糙,不够完善,但那也是我们开发团队每个成员辛勤努力的结果,我感到很欣慰。通过这次的网络大作业,我觉得自己有两方面的收获:首先是学会了怎么去和团队中的其他成员如何相处,如何合作,如何一起解决一个问题,明白了团队精神的重要性,也知道自己以后怎么去很好的融入一个团队。其次,在技术方面,我的工作是实现RSA和DES的加密和解密,通过实际的编程,对这方面的东西有了比较深的了解,可以说初步掌握了对数据的加密和解密。
浙公网安备 33010602011771号