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));
            }
  • 相关阅读:
    解决问题redis问题:ERR Client sent AUTH, but no password is set
    关于使用Git的几点小技巧
    解决linux中使用git,ssh每次都要输入密码
    No package tomcatX available. 解决办法
    关于spring定时任务被多次调用的问题
    vue 非常规跨域实现 proxyTable 设置及依赖
    css 3 获取设备宽度的方法
    ionic 文本域文字输入监听事件
    Ionic3学习基础之Input组件
    微信小程序tabBar使用
  • 原文地址:https://www.cnblogs.com/think/p/ConvertPem2048ToRSAParemeters.html
Copyright © 2011-2022 走看看