您的位置:首页 > 其它

.NET非对称加密(1)密钥生成与保存(新手教程)

2010-10-28 16:55 453 查看
当使用一个非对称加密类创建一个该类的实例的时候,构造函数会为我们生成一个"公钥/私钥"对。我们可以选择是否保存该密钥和保存的方式。

我们先从代码清单1-1的内容来熟悉下非对称密钥的密钥结构。

代码清单1-1输出非对称密钥

class Program
{
static void Main(string[] args)
{
RSACryptoServiceProvider rcp = new RSACryptoServiceProvider();
RSAParameters parameter1 = rcp.ExportParameters(true);
RSAParameters parameter2 = rcp.ExportParameters(false);

WriteParameInfo(parameter1,"parameter1");
WriteParameInfo(parameter2,"parameter2");
Console.Read();
}
private static void WriteParameInfo(RSAParameters parameter,string name)
{
Console.WriteLine(name+".D:");
Console.WriteLine(ConverBitTostring(parameter.D));
Console.WriteLine(name+"DP:");
Console.WriteLine(ConverBitTostring(parameter.DP));
Console.WriteLine(name+".DQ");
Console.WriteLine(ConverBitTostring(parameter.DQ));
Console.WriteLine(name+".InverseQ");
Console.WriteLine(ConverBitTostring(parameter.InverseQ));
Console.WriteLine(name+".Modulus");
Console.WriteLine(ConverBitTostring(parameter.Modulus));
Console.WriteLine(name+".P");
Console.WriteLine(ConverBitTostring(parameter.P));
Console.WriteLine(name+".Q");
Console.WriteLine(ConverBitTostring(parameter.Q));
Console.WriteLine(name + ".Exponent");
Console.WriteLine(ConverBitTostring(parameter.Exponent));
}
public static string ConverBitTostring(byte[] bytes)
{
if (bytes == null)
{
return "该值为空!";
}
else
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.Append(bytes[1].ToString());
}
return sb.ToString();
}
}
}
在代码清单1-1中,我们首先使用RSACryptoServiceProvider rcp = new RSACryptoServiceProvider();来生成RSA实现类的实例rcp,然后调用ExportParameters方法导出密钥。ExportParameters方法的参数是bool值,如果该值为true表示可以导出私钥,否则为不可导出私钥。密钥导出的结果为RSAParameters结构,在了解该结构的各个属性值之前我们先看看输出结果,parameter1的输出结果如图1-1所示,parameter2的输出结果如图1-2所示。



图1-1 parameter1的输出结果



图1-2 parameter2的输出结果
如果您对RSA算法的原理还不是很熟悉的话,建议您在看一看相关内容,这里为了叙述图1-1和图1-2中的输出结果,我再简要说明下RSA算法:

若要生成密钥对,可以从创建名为p和q的两个大的质数开始。这两个数相乘,结果称为n。因为p和q都是质数,所以n的全部因数为1、p、q和 n。如果仅考虑小于n的数,则与n为互质数(即与n没有公因数)的数的个数等于 (p - 1)(q - 1)。现在,选择一个数e,它与计算的值为互质数。则公钥表示为 {e, n}。若要创建私钥,则必须计算 d,它是满足 (d)(e) mod n = 1的一个数。根据 Euclidean 算法,私钥为{d, n}。纯文本m到密码文本c的加密定义为 c = (m ^ e) mod n。解密则定义为m = (c ^ d) mod n。

现在结合对RSA算法的简要说明,简单介绍RSAParameters的各个属性值的含义。

D:d,私钥指数。

DP:d mod (p - 1)。

DQ:d mod (q - 1)。

Exponent:e,公钥指数。

InverseQ:(InverseQ)(q) = 1 mod p。

Modulus:n。

P:p。

Q:q。

因为公钥是重复使用的,如果我们想使用导出的密钥,可以使用ImportParameters方法,导入RSAParameters结构。

如果我们想把密钥保存到本地文件中,我们可以使用ToXmlString方法把密钥导出到本地,如代码清单1-2所示。

代码清单1-2 导出密钥到XML

static void Main(string[] args)
{
RSACryptoServiceProvider rcp = new RSACryptoServiceProvider();
string keyString = rcp.ToXmlString(true);
FileStream fs = File.Create("e://key.xml");
fs.Write(Encoding.UTF8.GetBytes(keyString), 0, Encoding.UTF8.GetBytes(keyString).Length);
fs.Flush();

fs.Close();
Console.WriteLine(keyString);
Console.Read();
}
在代码清单1-2中,调用了rcp.ToXmlString(true)方法,返回XML字符串,然后把该字符串写入到本地磁盘E:的key.xml文件中。结果如图1-3所示。



图1-3 保存成功的XML文件
我们仍然可以使用FromXmlString方法来使用保存的密钥。

但是将密钥原封不动的存在本地文件中,密钥的安全性被完全破坏了,.NET为我们提供了安全的保存密钥的方式—密钥容器。代码清单1-3演示了如何将密钥保存到密钥容器中。

代码清单1-3 将密钥保存的密钥容器

CspParameters cp = new CspParameters();
cp.KeyContainerName = "xuanhunKeyContainer";
RSACryptoServiceProvider rcp = new RSACryptoServiceProvider(cp);
string keyString = rcp.ToXmlString(true);
FileStream fs = File.Create("e://key1.xml");
fs.Write(Encoding.UTF8.GetBytes(keyString), 0, Encoding.UTF8.GetBytes(keyString).Length);
fs.Flush();
fs.Close();
代码清单1-3中,我们初始化了CspParameters实例cp,然后为该实例的属性KeyContainerName赋值为"xuanhunKeyContainer"。然后在初始化RSACryptoServiceProvider实例的时候传入cp,这样密钥就保存在了密钥容器中。为了测试这段程序是不是如预期的这样,我们关闭程序然后运行如代码清单1-4所示的代码。

代码清单1-5 获取密钥容器中的密钥

CspParameters cp = new CspParameters();
cp.KeyContainerName = "xuanhunKeyContainer";
RSACryptoServiceProvider rcp = new RSACryptoServiceProvider(cp);
string keyString = rcp.ToXmlString(true);
FileStream fs = File.Create("e://key2.xml");
fs.Write(Encoding.UTF8.GetBytes(keyString), 0, Encoding.UTF8.GetBytes(keyString).Length);
fs.Flush();

fs.Close();
代码清单1-5和代码清单1-4几乎是一模一样的,那么获取密钥的机制是什么呢?如果系统中不存在指定名称的密钥容器那么当我们执行以上代码时会创建新的密钥容器,如果存在,则从存在的密钥容器中加载密钥。为了测试,在代码清单中1-5与1-4中我仍然生成了两个新的XML文件,key.xml和key2.xml,如果两个文件一模一样,说明密钥保存在了系统的密钥容器中,可以被反复利用,否则不然。在命令行使用cp命令,结果如图1-4所示。



图1-4 比对key.xml和key2.xml
如图1-4,证明了我们可以将密钥保存到系统的密钥容器中。

转自:

http://www.myext.cn/csharp/5883.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐