• .NET使用OpenSSL生成的pem密钥文件


    NET要使用OpenSSL生成的pem密钥文件,网上资料很少(http://www.faqs.org/rfcs/rfc1421.html,RFC1421文件又老长老长),仅有的资料还是有错误的,所以今天干了件体力活,把PEM密钥文件610个字节一个个看过来,终于搞清了它的格式。

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

    namespace Thinhunan.Cnblogs.Com.RSAUtility
    {
        public class PemConverter
        {
            /// <summary>
            /// 将pem格式公钥转换为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(" ", "").Replace(" ", "");
                byte[] keyData = Convert.FromBase64String(pemFileConent);
                if (keyData.Length < 162)
                {
                    throw new ArgumentException("pem file content is incorrect.");
                }
                byte[] pemModulus = new byte[128];
                byte[] pemPublicExponent = new byte[3];
                Array.Copy(keyData, 29, pemModulus, 0, 128);
                Array.Copy(keyData, 159, pemPublicExponent, 0, 3);
                RSAParameters para = new RSAParameters();
                para.Modulus = pemModulus;
                para.Exponent = pemPublicExponent;
                return para;
            }

            /// <summary>
            /// 将pem格式私钥转换为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(" ", "").Replace(" ","");
                byte[] keyData = Convert.FromBase64String(pemFileConent);
                if (keyData.Length < 609)
                {
                    throw new ArgumentException("pem file content is incorrect.");
                }

                int index = 11;
                byte[] pemModulus = new byte[128];
                Array.Copy(keyData, index, pemModulus, 0, 128);

                index += 128;
                index += 2;//141
                byte[] pemPublicExponent = new byte[3];
                Array.Copy(keyData, index, pemPublicExponent, 0, 3);

                index += 3;
                index += 4;//148
                byte[] pemPrivateExponent = new byte[128];
                Array.Copy(keyData, index , pemPrivateExponent, 0, 128);

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

                index += 64;
                index += ((int)keyData[index + 1] == 64 ? 2 : 3);//346
                byte[] pemPrime2 = new byte[64];
                Array.Copy(keyData, index , pemPrime2, 0, 64);

                index += 64;
                index += ((int)keyData[index + 1] == 64 ? 2 : 3);//412/413
                byte[] pemExponent1 = new byte[64];
                Array.Copy(keyData,index, pemExponent1, 0, 64);

                index += 64;
                index += ((int)keyData[index + 1] == 64 ? 2 : 3);//479/480
                byte[] pemExponent2 = new byte[64];
                Array.Copy(keyData, index, pemExponent2, 0, 64);

                index += 64;
                index += ((int)keyData[index + 1] == 64 ? 2 : 3);//545/546
                byte[] pemCoefficient = new byte[64];
                Array.Copy(keyData, index, pemCoefficient, 0, 64);

                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;
            }
           
        }
    }


    测试pem导成RSAParameters成功,使用通过:
    using System;
    using System.Security.Cryptography;
    using System.Text;
    using System.IO;
    using System.Web;

    namespace Thinhunan.Cnblogs.Com.RSAUtility
    {
        class Program
        {
            #region keys

            const string PUBLICKEY =
    @"-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpsDr+W45aFHIkvotZaGK/THlF
    FpuZfUtghhWkHAm3H7yvL42J4xHrTr6IeUDCl4eKe6qiIgvYSNoL3u4SERGOeYmV
    1F+cocu9IMGnNoicbh1zVW6e8/iGT3xaYQizJoVuWA/TC/zdds2ihCJfHDBDsouO
    CXecPapyWCGQNsH5sQIDAQAB
    -----END PUBLIC KEY-----";

            const string PRIVATEKEY =
    @"-----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQDpsDr+W45aFHIkvotZaGK/THlFFpuZfUtghhWkHAm3H7yvL42J
    4xHrTr6IeUDCl4eKe6qiIgvYSNoL3u4SERGOeYmV1F+cocu9IMGnNoicbh1zVW6e
    8/iGT3xaYQizJoVuWA/TC/zdds2ihCJfHDBDsouOCXecPapyWCGQNsH5sQIDAQAB
    AoGBAM/JbFs4y5WbMncrmjpQj+UrOXVOCeLrvrc/4kQ+zgCvTpWywbaGWiuRo+cz
    cXrVQ6bGGU362e9hr8f4XFViKemDL4SmJbgSDa1K71i+/LnnzF6sjiDBFQ/jA9SK
    4PYrY7a3IkeBQnJmknanykugyQ1xmCjbuh556fOeRPaHnhx1AkEA/flrxJSy1Z+n
    Y1RPgDOeDqyG6MhwU1Jl0yJ1sw3Or4qGRXhjTeGsCrKqV0/ajqdkDEM7FNkqnmsB
    +vPd116J6wJBAOuNY3oOWvy2fQ32mj6XV+S2vcG1osEUaEuWvEgkGqJ9co6100Qp
    j15036AQEEDqbjdqS0ShfeRSwevTJZIap9MCQCeMGDDjKrnDA5CfB0YiQ4FrchJ7
    a6o90WdAHW3FP6LsAh59MZFmC6Ea0xWHdLPz8stKCMAlVNKYPRWztZ6ctQMCQQC8
    iWbeAy+ApvBhhMjg4HJRdpNbwO6MbLEuD3CUrZFEDfTrlU2MeVdv20xC6ZiY3Qtq
    /4FPZZNGdZcSEuc3km5RAkApGkZmWetNwDJMcUJbSBrQMFfrQObqMPBPe+gEniQq
    Ttwu1OULHlmUg9eW31wRI2uiXcFCJMHuro6iOQ1VJ4Qs
    -----END RSA PRIVATE KEY-----";

            #endregion

            static void Main(string[] args)
            {           
               
                TestSignAndVerify();
               
            }


            public static void TestSignAndVerify()
            {
                //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("ok");
                }
                else
                {
                    Console.WriteLine("no");
                }

            }

        }
    }

    作者 THINK(谭振林)
     

  • 相关阅读:
    机器学习-数据可视化神器matplotlib学习之路(四)
    [AspNetCore]CookieAuthentication禁用自动跳转到登录页
    [AspNetCore3.1] 使用Serilog记录日志
    [排序算法二]选择排序
    [排序算法一]冒泡排序
    Ocelot 网关 和 consul 服务发现
    AspNetCore3.0 和 JWT
    在AspNetCore3.0中使用Autofac
    【ElasticSearch+NetCore 第二篇】Nest封装
    【ElasticSearch+NetCore 第一篇】在Windows上安装部署ElasticSearch和ElasticSearch-head
  • 原文地址:https://www.cnblogs.com/adylee/p/3625388.html
Copyright © 2020-2023  润新知