.NET使用OpenSSL生成的pem密钥文件(增加size为2048的密钥转换)【做电子商务的朋友可能需要】...

上篇随笔  .NET使用OpenSSL生成的pem密钥文件【做电子商务的朋友可能需要】 的算法只支持1024位的密钥文件导入.NET,今天把2048位的支持加上:

using  System;
using  System.Text;
using  System.Security.Cryptography;
using  System.Web;
using  System.IO;

namespace  Thinhunan.Cnblogs.Com.RSAUtility
{
    
///   <summary>
    
///  Author  http://thinhunan.cnblogs.com
    
///   </summary>
     public   class  PemConverter
    {
        
///   <summary>
        
///  将pem格式公钥(1024 or 2048)转换为RSAParameters
        
///   </summary>
        
///   <param name="pemFileConent"> pem公钥内容 </param>
        
///   <returns> 转换得到的RSAParamenters </returns>
         public   static  RSAParameters ConvertFromPemPublicKey( string  pemFileConent)
        {
            
if  ( string .IsNullOrEmpty(pemFileConent))
            {
                
throw   new  ArgumentNullException( " pemFileConent " " This arg cann't be empty. " );
            }
            pemFileConent 
=  pemFileConent.Replace( " -----BEGIN PUBLIC KEY----- " "" ).Replace( " -----END PUBLIC KEY----- " "" ).Replace( " \n " "" ).Replace( " \r " "" );
            
byte [] keyData  =  Convert.FromBase64String(pemFileConent);
            
bool  keySize1024  =  (keyData.Length  ==   162 );
            
bool  keySize2048  =  (keyData.Length  ==   294 );
            
if  ( ! ( keySize1024  ||  keySize2048 ))
            {
                
throw   new  ArgumentException( " pem file content is incorrect, Only support the key size is 1024 or 2048 " );
            }
            
byte [] pemModulus  =  (keySize1024 ?   new   byte [ 128 ] :  new   byte [ 256 ]);
            
byte [] pemPublicExponent  =   new   byte [ 3 ];
            Array.Copy(keyData, (keySize1024
?   29 : 33 ), pemModulus,  0 ,(keySize1024 ?    128 : 256 ));
            Array.Copy(keyData, (keySize1024
?   159 : 291 ), pemPublicExponent,  0 3 );
            RSAParameters para 
=   new  RSAParameters();
            para.Modulus 
=  pemModulus;
            para.Exponent 
=  pemPublicExponent;
            
return  para;
        }

        
///   <summary>
        
///  将pem格式私钥(1024 or 2048)转换为RSAParameters
        
///   </summary>
        
///   <param name="pemFileConent"> pem私钥内容 </param>
        
///   <returns> 转换得到的RSAParamenters </returns>
         public   static  RSAParameters ConvertFromPemPrivateKey( string  pemFileConent)
        {
            
if  ( string .IsNullOrEmpty(pemFileConent))
            {
                
throw   new  ArgumentNullException( " pemFileConent " " This arg cann't be empty. " );
            }
            pemFileConent 
=  pemFileConent.Replace( " -----BEGIN RSA PRIVATE KEY----- " "" ).Replace( " -----END RSA PRIVATE KEY----- " "" ).Replace( " \n " "" ).Replace( " \r " , "" );
            
byte [] keyData  =  Convert.FromBase64String(pemFileConent);

            
bool  keySize1024  =  (keyData.Length  ==   609   ||  keyData.Length  ==   610 );
            
bool  keySize2048  =  (keyData.Length  ==   1190   ||  keyData.Length  ==   1192 );
           
            
if  ( ! (keySize1024  ||  keySize2048))
            {
                
throw   new  ArgumentException( " pem file content is incorrect, Only support the key size is 1024 or 2048 " );
            }

            
int  index  =  ( keySize1024  ?   11  :  12 );
            
byte [] pemModulus  =   ( keySize1024  ?   new   byte [ 128 ]: new   byte [ 256 ]);
            Array.Copy(keyData, index, pemModulus, 
0 , pemModulus.Length);

            index 
+=  pemModulus.Length;
            index 
+=   2 ;
            
byte [] pemPublicExponent  =   new   byte [ 3 ];
            Array.Copy(keyData, index, pemPublicExponent, 
0 3 );

            index 
+=   3 ;
            index 
+=   4 ;
            
if  (( int )keyData[index]  ==   0 )
            {
                index
++ ;
            }
            
byte [] pemPrivateExponent  =  (keySize1024  ?   new   byte [ 128 ] :  new   byte [ 256 ]);
            Array.Copy(keyData, index , pemPrivateExponent, 
0 , pemPrivateExponent.Length);

            index 
+=  pemPrivateExponent.Length;
            index 
+=  (keySize1024 ?  (( int )keyData[index + 1 ==   64 ? 2 3 ):(( int )keyData[index + 2 ==   128   ? 3 : 4 ));
            
byte [] pemPrime1  =  (keySize1024  ?   new   byte [ 64 ] :  new   byte [ 128 ]);
            Array.Copy(keyData, index, pemPrime1, 
0 , pemPrime1.Length);

            index 
+=  pemPrime1.Length;
            index 
+=  (keySize1024  ?  (( int )keyData[index  +   1 ==   64   ?   2  :  3 ) : (( int )keyData[index  +   2 ==   128   ?   3  :  4 ));
            
byte [] pemPrime2  =  (keySize1024  ?   new   byte [ 64 ] :  new   byte [ 128 ]);
            Array.Copy(keyData, index , pemPrime2, 
0 , pemPrime2.Length);

            index 
+=  pemPrime2.Length;
            index 
+=  (keySize1024  ?  (( int )keyData[index  +   1 ==   64   ?   2  :  3 ) : (( int )keyData[index  +   2 ==   128   ?   3  :  4 ));
            
byte [] pemExponent1  =  (keySize1024  ?   new   byte [ 64 ] :  new   byte [ 128 ]);
            Array.Copy(keyData,index, pemExponent1, 
0 , pemExponent1.Length);

            index 
+=  pemExponent1.Length;
            index 
+=  (keySize1024  ?  (( int )keyData[index  +   1 ==   64   ?   2  :  3 ) : (( int )keyData[index  +   2 ==   128   ?   3  :  4 ));
            
byte [] pemExponent2  =  (keySize1024  ?   new   byte [ 64 ] :  new   byte [ 128 ]);
            Array.Copy(keyData, index, pemExponent2, 
0 , pemExponent2.Length);

            index 
+=  pemExponent2.Length;
            index 
+=  (keySize1024  ?  (( int )keyData[index  +   1 ==   64   ?   2  :  3 ) : (( int )keyData[index  +   2 ==   128   ?   3  :  4 ));
            
byte [] pemCoefficient  =  (keySize1024  ?   new   byte [ 64 ] :  new   byte [ 128 ]);
            Array.Copy(keyData, index, pemCoefficient, 
0 , pemCoefficient.Length);

            RSAParameters para 
=   new  RSAParameters();
            para.Modulus 
=  pemModulus;
            para.Exponent 
=  pemPublicExponent;
            para.D 
=  pemPrivateExponent;
            para.P 
=  pemPrime1;
            para.Q 
=  pemPrime2;
            para.DP 
=  pemExponent1;
            para.DQ 
=  pemExponent2;
            para.InverseQ 
=  pemCoefficient;
            
return  para;
        }
        
    }
}


测试加、解密,签名验证功能通过:
         static   void  Main( string [] args)
        {
            
string  privateKey  =  GetPemContent( @" C:\ftzl\privatekey2048.pem " );
            
string  publicKey  =  GetPemContent( @" c:\ftzl\publickey2048.pem " );

            
// DebugRsaKey(privateKey,true);
            TestSignAndEncrypt(privateKey,publicKey);
            
// TestVerifyOATransferSign();
        }

        
static   string  GetPemContent( string  filePath)
        {
            
string  content  =  File.ReadAllText(filePath, Encoding.ASCII);
            
return  content;
        }
        
public   static   void  TestSignAndEncrypt( string  privateKey, string  publicKey)
        {
            
// sign
            RSAParameters para  =  PemConverter.ConvertFromPemPrivateKey(privateKey);
            RSACryptoServiceProvider rsa 
=   new  RSACryptoServiceProvider();
            rsa.ImportParameters(para);
            
byte [] testData  =  Encoding.UTF8.GetBytes( " hello " );
            MD5CryptoServiceProvider md5 
=   new  MD5CryptoServiceProvider();
            
byte [] signData  =  rsa.SignData(testData, md5);

            
// verify
            RSAParameters paraPub  =  PemConverter.ConvertFromPemPublicKey(publicKey);
            RSACryptoServiceProvider rsaPub 
=   new  RSACryptoServiceProvider();
            rsaPub.ImportParameters(paraPub);
            
if  (rsaPub.VerifyData(testData, md5, signData))
            {
                Console.WriteLine(
" verify sign successful " );
            }
            
else
            {
                Console.WriteLine(
" verify sign failed " );
            }

            
// encrypt and decrypt data
             byte [] encryptedData  =  rsaPub.Encrypt(testData,  false );
            
byte [] decryptedData  =  rsa.Decrypt(encryptedData,  false );

            Console.WriteLine(Encoding.UTF8.GetString(decryptedData));
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值