.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, 03);
            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, 
03);

            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?23):((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));
        }
posted @ 2009-09-10 13:50  Think  阅读(5727)  评论(9编辑  收藏  举报