zoukankan      html  css  js  c++  java
  • .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));
            }
  • 相关阅读:
    使用 Dockerfile 定制镜像
    UVA 10298 Power Strings 字符串的幂(KMP,最小循环节)
    UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)
    LeetCode Best Time to Buy and Sell Stock 买卖股票的最佳时机 (DP)
    LeetCode Number of Islands 岛的数量(DFS,BFS)
    LeetCode Triangle 三角形(最短路)
    LeetCode Swap Nodes in Pairs 交换结点对(单链表)
    LeetCode Find Minimum in Rotated Sorted Array 旋转序列找最小值(二分查找)
    HDU 5312 Sequence (规律题)
    LeetCode Letter Combinations of a Phone Number 电话号码组合
  • 原文地址:https://www.cnblogs.com/think/p/ConvertPem2048ToRSAParemeters.html
Copyright © 2011-2022 走看看