.net下的数字签名

转载自:http://www.cnblogs.com/jams742003/archive/2010/04/09/1708315.html

 

在上一篇中,说了说数字签名。

数字签名是建立在密钥对体系基础上的:数字签名(信息摘要,私钥),验证签名(数字签名,公钥)。

对于公钥和私钥可以这样理解:

密文=加密(AB,原文),原文=解密(AB,密文),其中AB就是密钥对。

 

.net下的System.Security.Cryptography 名字空间是提供加密服务的一个空间。在边有大量用于实现加密服务的类,例如哈希散列,随机数字等。这个在前边两篇(1)和(2)中进行了说明。

 

公钥加密又叫非对称加密,即由一个密钥(公钥)加密,须由另一个密钥(私钥)解密。.net下的非对称加密提供了DSA RSA加密。

DSA,是Digital Signature Algorithm的缩写,是一种签名算法。RSA,是一种可以用于签名,也可以用于加密的一种算法。

这个空间提供了DSA加密的类型:

System.Security.Cryptography.DSA

System.Security.Cryptography.DSACryptoServiceProvider

 

若是DSA是一个抽象基类。通过DSA算法可以创建数字签名,用于保护数据的完整性。支持的密钥长度为5121024,以64位的整数倍递增。

 

RSA加密的类型:

System.Security.Cryptography.RSA

System.Security.Cryptography.RSACryptoServiceProvider

 

这里引用一段话:

与非托管 CAPI 中的 RSA 实现不同的是,RSACryptoServiceProvider 类会在加密之后、解密之前颠倒被加密数组的字节顺序。默认情况下,CAPI CryptDecrypt 函数无法解密由 RSACryptoServiceProvider 类加密的数据,RSACryptoServiceProvider 类无法解密由 CAPI CryptEncrypt 方法加密的数据。如果在 API 之间互相操作时没有对颠倒的顺序进行补偿,RSACryptoServiceProvider 类会引发 CryptographicException。要同 CAPI 相互操作,必须在加密数据与其他 API 相互操作之前,手动颠倒加密字节的顺序。通过调用 Array.Reverse 方法可轻松颠倒托管字节数组的顺序。

它支持3841024位密钥,以8位的整数倍递增。

 

现在来为一段数据进行数字签名,这里用到的类是DSA驱动提供的方法:

数字签名=加密(信息摘要,私钥),信息摘要=hash(数据)

 

 

[Test]
public   void  TestDSADigitalSignature()
{
    
// 原文
     string  strContent  =   " 12345abc " ;

    
// 信息摘要,sha1
    SHA1 _sha1  =   new  SHA1CryptoServiceProvider();
 

    Encoding _encoding 
=  Encoding.Default;
    
byte [] bb  =  _encoding.GetBytes(strContent);
    
byte [] bMessageDigest  =  _sha1.ComputeHash(bb);
    DSACryptoServiceProvider _DSA 
=   new  DSACryptoServiceProvider();

    Console.WriteLine(
" 信息摘要:{0} " ,

    BitConverter.ToString(bMessageDigest).Replace(
" - " , string .Empty)); 

    
// 通过私钥进行签名
     
// --------------------------------------------
    DSAParameters _privateKey  =  _DSA.ExportParameters( true );

    _DSA.ImportParameters(_privateKey);
    DSASignatureFormatter DSAFormatter 
=   new  DSASignatureFormatter(_DSA);

    DSAFormatter.SetHashAlgorithm(
" sha1 " );
    
byte [] bSignature  =  DSAFormatter.CreateSignature(bMessageDigest);

    Console.WriteLine(
" 数字签名:{0} "

    BitConverter.ToString(bSignature).Replace(
" - " string .Empty));
    
// --------------------------------------------
 

    
// 通过公钥进行验证签名
    
// --------------------------------------------

    DSAParameters _publicKey 
=  _DSA.ExportParameters( false );
    _DSA.ImportParameters(_privateKey);

    DSASignatureDeformatter DSADeformatter 
=   new  DSASignatureDeformatter(_DSA);
    DSADeformatter.SetHashAlgorithm(
" sha1 " );

    
bool  bCheck  =  DSADeformatter.VerifySignature(bMessageDigest, bSignature);

    Console.WriteLine(
" 验证签名是否通过:{0} " ,bCheck == true ? " " : " " );
    
// --------------------------------------------  
}

 

说明一下:

·私钥生成:ExportParameters(true)

·公钥生成:ExportParameters(false)

·生成签名:DSAFormatter.CreateSignature(bMessageDigest)

·验证签名:

DSADeformatter.VerifySignature(bMessageDigest, bSignature)

 

结果:

信息摘要:CBFC425ADABD72095739CB720F5BB7026

数字签名:BA069C3DEB188D03362B10668ABF67031455E47E40

3B94380E132B62EFE621051356397EC7E05D

验证签名是否通过:是

RSA驱动提供的也以这个示例:

 

public   void  TestRSADigitalSignature()
{
    
// 原文
     string  strContent  =   " 12345abc " ;
    Encoding _encoding 
=  Encoding.Default;

    
byte [] bb  =  _encoding.GetBytes(strContent);
    
byte [] bEncrypt;
    
byte [] bDecrypt; 

    RSACryptoServiceProvider _RSA 
=   new  RSACryptoServiceProvider();

    RSAParameters _publicKey 
=  _RSA.ExportParameters( false );
    RSAParameters _privateKey 
=  _RSA.ExportParameters( true );

 

    
// 用公钥,加密
    
// --------------------------------------------

    RSACryptoServiceProvider _RSA1 
=   new  RSACryptoServiceProvider();
    _RSA1.ImportParameters(_publicKey);
    bEncrypt 
=  _RSA1.Encrypt(bb,  false );
    Console.WriteLine(
" 加密后的数据:{0} "
    BitConverter.ToString(bEncrypt).Replace(
" - " string .Empty));

    
// --------------------------------------------

    
// 通过私钥进行解密
    
// --------------------------------------------

    RSACryptoServiceProvider _RSA2 
=   new  RSACryptoServiceProvider();
    _RSA2.ImportParameters(_privateKey);
    bDecrypt 
=  _RSA.Decrypt(bEncrypt,  false );
    
string  str  =  _encoding.GetString(bDecrypt);
    Console.WriteLine(
" 解密后的数据:{0} " , str);

    
// --------------------------------------------  
}

 

结果:

加密后的数据:A9B15B4A0C2C976A8C990E739DFE6CD192EE2ACB00EA

C487E1BE2128A3E8241EFAF0F98AC88C4A53ADC48D9AA9D9585A4D0FB5

5EC6651C40ADB88EE2C28032A84C25B70103233BADEB518F97E54F3CF9

920FAC642D79F0BCB37BF7E22054CE44CD5B8295F7CDC034299D4F836D

B0CF48C0011CE148D6AD5FF5C892A1B90F81BB

解密后的数据:abc

 

对于非对称加密的密钥的存储

对私钥来说可以存放到容器中。之前先看一下.net提供的非对称加密类型的构造器,以RSA为例:

RSACryptoServiceProvider() 
RSACryptoServiceProvider(CspParameters) 
RSACryptoServiceProvider(Int32)
RSACryptoServiceProvider(Int32, CspParameters)

 

 

这是它的四个构造器,以第二个为例:

public  RSACryptoServiceProvider(CspParameters parameters)

 

 

下面生成密钥并存放到容器中:

CspParameters cspParams  =   new  CspParameters();
cspParams.KeyContainerName 
=   " selfContainer " ;  

// 创建一个key,并添加到容器中
RSACryptoServiceProvider _key  =   new  RSACryptoServiceProvider(cspParams);

 

 

一个完整的示例:

public   void  TestCreateContainer()
{
    Encoding _encoding 
=  Encoding.Default; 

    
string  strContent  =   " 12345abc " ;
    
byte [] dataToEncrypt  =  _encoding.GetBytes(strContent); 

    
byte [] encryptedData;
    
byte [] decryptedData; 

    
// 容器

    CspParameters cspParams 
=   new  CspParameters();
    cspParams.KeyContainerName 
=   " selfContainer " ;
 

    
// 创建一个key,并添加到容器中
    RSACryptoServiceProvider _key  =   new  RSACryptoServiceProvider(cspParams); 

    
// 加密
    RSACryptoServiceProvider _RSA1  =   new  RSACryptoServiceProvider(cspParams);
    encryptedData 
=  _RSA1.Encrypt(dataToEncrypt,  false );
 
    
// 解密
    RSACryptoServiceProvider _RSA2  =   new  RSACryptoServiceProvider(cspParams);
    decryptedData 
=  _RSA1.Decrypt(encryptedData,  false );
    
string  str  =  _encoding.GetString(decryptedData);

    Console.WriteLine(str);
}

 

 

1)创建非对称密钥并保存在容器中的步骤:

·创建CspParameters类的实例,且设置其KeyContainerName属性

·通过带有CspParameters参数的构造器来创建实例从AsymmetricAlgorithm类派生的类的实例,通常是RSADSA实例,参数就是上一步中的CspParameters对象

2)从容器中删除非对称密钥

·创建CspParameters类实例,且为其属性KeyContainerName指定名字

·通过带CspParameters参数的构造器创建从AsymmetricAlgorithm类派生的类的实例,派生类一般指RSADSA

·设置派生类实例的属性PersistKeyInCSPfalse

·调用派生类的Clear方法,这个方法用于释放资源并清除密钥容器 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值