当前位置:编程学习 > 网站相关 >>

net加密基础2-非对称加密

非对称密码算法
非对称密码算法使用2个不同但在数学上却相关的密钥。用于加密数据的密钥不能用于解密。
非对称密码技术统称称为“公钥加密技术”,没有双方必要保密的单个密钥。
公钥加密技术只有一个必须由一方保密的私钥,第二个密钥就是公钥,任何想与他们通信的人都可以随意使用它。
安全web通信就是采用的这种技术。该技术可以用于电子商务。
 
非对称和对称的区别
对称加密和非对称加密的密钥类型分别是私钥和公钥。
 
对称加密使用的是私钥加密,也就是密钥只能是加密者和解密者知道,第3方不能知道。
而非对称加密情况完全不一样,非对称加密有2个不同的密钥,一个是公共的密钥,一个是私有的密钥,公钥是可以让外人知道的,因为公钥只用来加密数据,而私钥只能由解密方知道,只有私钥能解密!
 
官方的啰嗦!
公钥加密使用一个必须对未经授权的用户保密的私钥和一个可以对任何人公开的公钥。公钥和私钥都在数学上相关联;用公钥加密的数据只能用私钥解密,而用私钥签名的数据只能用公钥验证。公钥可以提供给任何人;公钥用于对要发送到私钥持有者的数据进行加密。两个密钥对于通信会话都是唯一的。公钥加密算法也称为不对称算法,原因是需要用一个密钥加密数据而需要用另一个密钥来解密数据。
 
经典的小红和小明
双方(小红和小明)可以按照下列方式使用公钥加密。首先,小红生成一个公钥/私钥对。如果小明想要给小红发送一条加密的消息,他将向她索要她的公钥。小红通过不安全的网络将她的公钥发送给小明,小明接着使用该密钥加密消息。(如果小明在不安全的信道如公共网络上收到小红的密钥,则小明必须同小红验证他具有她的公钥的正确副本。)小明将加密的消息发送给小红,而小红使用她的私钥解密该消息。
 
但是,在传输小红的公钥期间,未经授权的代理可能截获该密钥。而且,同一代理可能截获来自小明的加密消息。但是,该代理无法用公钥解密该消息。该消息只能用小红的私钥解密,而该私钥没有被传输。小红不使用她的私钥加密给小明的答复消息,原因是任何具有公钥的人都可以解密该消息。如果小红想要将消息发送回小明,她将向小明索要他的公钥并使用该公钥加密她的消息。然后,小明使用与他相关联的私钥来解密该消息。
 
在一个实际方案中,小红和小明使用公钥(不对称)加密来传输私(对称)钥,而对他们的会话的其余部分使用私钥加密。



NET中的非对称加密算法类
算法 抽象算法类 默认实现类 有效密钥大小(位) 默认密钥大小(位)
RSA RSA RSACryptoServiceProvider 364-16384 1024
DSA DSA DSACryptoServiceProvider 364-512 1024

注意:公钥加密算法使用固定的缓冲区大小,而私钥加密算法使用长度可变的缓冲区。公钥算法无法像私钥算法那样将数据链接起来成为流,原因是它只可以加密少量数据。因此,不对称操作不使用与对称操作相同的流模型。

所有的非对称加密算法都是由AsymmetricAlgorithm类派生。

\
非对称RSA加密算法


实际使用中很少直接用RSA类来实现加密算法,因为它们采用不进行填充的原始计算。而是使用RSACryptoServiceProvider实现类的加密和解密方法
publicbyte[] Decrypt(byte[] rgb, boolfOAEP);
publicbyte[] Encrypt(byte[] rgb, boolfOAEP);

创建个rsa算法的对象
RSACryptoServiceProviderrsa = newRSACryptoServiceProvider();

我们怎么获取公钥和私钥信息?
之前的对称算法可以获取算法的key和IV信息。
但是非对称算法不提供可以用于检索密钥信息的任何属性!如果需要保存密钥信息供以后使用,就只能用ToXmlString()方法输出密钥对的信息。
publicoverridestringToXmlString(boolincludePrivateParameters);
这个布尔参数如果设置为true,那么就会输出带私钥的xml,如果是false,那么就只输出带公钥的xml。

尝试输出完整的密钥对
rsa.ToXmlString(true)
----------------------------完整的密钥对信息-----------------------------
<RSAKeyValue>
<Modulus>yvGBq09qcWhIi+u3UHGK0EH5zav018FVGM+BPiXK23nFZeRky9HLrOH9DP5Bc7NXyBxoE0MC3YmaG68tr6nHtLhI7
TVshAsfMX1E2BjTfLq1wHhcFwTJSvyNpwnR9NHMZsDE166XgRQ5vHkfFwBWvk7F8YVcACKp3Y6OcvAcp1s=</Modulus>
<Exponent>AQAB</Exponent>
<P>7+9YUu/6SFlOW4RrON/Lie+bMSmOZB/wfqj9AAdmX+n8joPQ/WLA69/CtetzIZ6KIOkD2fd8MFiFrjoHSXmpUQ==</P>
<Q>2IgZma4hTV3EWFP3TXasajl23oRoLBeuWZldu+Q2pyeCwuBE6Mmp2aTbXauPGw3ptUAX/8pw0QyI/6i0b3wa6w==</Q>
<DP>F4AW45Czr/BnV1lh8yEgW3NHfQo38yCZup4soZsX8N8HKKJKjvbkNHYnKRBVp35SwyRvhyLRXB7fgRAX9J9g8Q==</DP>
<DQ>SSgCbje0rKznb2g+/37+1YzAqoFVqL//eeolDxwVkvf4Z9rZrUSlDBF0w/r4iI10znXvJc7Buv9fMfFPtPLbLQ==</DQ>
<InverseQ>pJ37e7nw8Joy2dmnrYf5urx88NQz1TBKZF/xGReSeTiBsbkugqkoHWvX6GoWV8TL7Gx9ZRmAma/rs3YWQbk00Q==</InverseQ>
<D>PrjbibW2wSwo183XTy54Z5sseIt/1brz8QIZALsvchu1jaNEH9ZMa7dAvWZLllXEeJ2G8QUR+qRPk+TVaug/RydliAPdf11h+7nnIoNOzk4LJtBFmNROPXTOLNwap+GJWIQM1Hd72V4kDiv1He3HUNLsLgGmUelDWekISUzrYOE=</D>
</RSAKeyValue>

上面的xml信息可以在我们需要使用的时候导入到算法里面。

只输出公钥信息
rsa.ToXmlString(false)
----------------------------只包含公钥信息-----------------------------
<RSAKeyValue>
<Modulus>igBXA4/oLVLNP+r9jxdx1lLfqNNkSUOe0ApKql8/jmUGc/dIzSMF6bgBcvw5dBxXncYVXxrtk7
AEilemz8PQui07M0NbJ4IeGQzRcJJNlAsQJvGWTydaoH/xLm4I0wH13RG2V9
UjcOYPMOHBEapB4Flkst44qqclw8SVuh55OWk=</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>

一个简单的RSA例子
RSA简单例子
static void Main()
{
    Byte[] StrByte = Encoding.UTF8.GetBytes("我是明文");
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    string str = RSAEncryptor(rsa.ToXmlString(false), StrByte);
    Console.WriteLine("密文:{0}", str);
    Encoding en = Encoding.UTF8;
    Console.WriteLine("明文:{0}", RSADecryptor(rsa.ToXmlString(true), Convert.FromBase64String(str), en));
    Console.Read();
}

public static string RSAEncryptor(string XMLKey, byte[] Str)
{
    try
    {
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(XMLKey);
        return Convert.ToBase64String(rsa.Encrypt(Str, false));
    }
    catch (CryptographicException e)
    {
        Console.WriteLine(e.Message);
        return null;
    }
}

public static string RSADecryptor(string XMLKey, byte[] Str, Encoding en)
{
    try
    {
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(XMLKey);
        return en.GetString(rsa.Decrypt(Str, false));
    }
    catch (CryptographicException e)
    {
        Console.WriteLine(e.Message);
        return null;
    }
}

\
如果给解密的RSA对象传输个不包含私钥的XML,那么就会异常了,
你可以讲上面调用解密的代码修改成下面这样,就能得到异常了
Console.WriteLine("明文:{0}", RSADecryptor(rsa.ToXmlString(false), Convert.FromBase64String(str), en));

使用参数来传递密钥信息


RSAParameters
RSACryptoServiceProvider有2个方法可以导出RSAParameters类型的参数对象。
在使用加密解密算法的时候我们就只需要传递RSAParameters对象

将上面的代码成使用RSAParameters
使用RSAParameters
static void Main()
{
    Byte[] StrByte = Encoding.UTF8.GetBytes("使用RSAParameters");
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    string str = RSAE
补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,