C#下实现RSA公钥私钥由pcks8格式(java)转化为pcks1格式(非java)

本文介绍如何使用BouncyCastle库将PKCS#8格式的RSA公钥和私钥转换为PKCS#1格式,并提供了一种通过简单移除PKCS#8头部信息来实现转换的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于Pcks不了解的可以先看下 PKCS标准,然后这里暂时只有pcks8格式转化为pcks1格式,暂时还没能找到直接通过BouncyCastle来转化pcks1格式到pcks8格式的方法或代码(当然可以借由RSACryptoServiceProvider来进行读取,然后再进行间接的转化),只找到了 通过openssl来转化pcks1到pcks8的方法,以下为代码:
    using Org.BouncyCastle.Asn1.Pkcs;
    using Org.BouncyCastle.Asn1.X509;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.X509;
    /// <summary>
    /// PKCS转化辅助类
    /// </summary>
    public class RSAPcksTransferHelper
    {
        /// <summary>
        /// 将pcks8格式的RSA公钥转化为pcks1格式
        /// </summary>
        /// <param name="pubicKey">pcks8格式的RSA公钥 base64格式</param>
        /// <returns>pcks1格式的RSA公钥 base64格式</returns>
        public static string ConvertPublicKeyPkcs8ToPcks1(string pubicKey)
        {
            return Convert.ToBase64String(ConvertPublicKeyPkcs8ToPcks1(Convert.FromBase64String(pubicKey)));
        }
        /// <summary>
        /// 将pcks8格式的RSA公钥转化为pcks1格式
        /// </summary>
        /// <param name="pubicKey">pcks8格式的RSA公钥</param>
        /// <returns>pcks1格式的RSA公钥</returns>
        public static byte[] ConvertPublicKeyPkcs8ToPcks1(byte[] pubicKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(pubicKey);
            SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKeyParam);
            return spkInfo.GetPublicKey().ToAsn1Object().GetEncoded();
        }
        /// <summary>
        /// 将pcks8格式的RSA私钥转化为pcks1格式
        /// </summary>
        /// <param name="privateKey">pcks8格式的RSA私钥 base64格式</param>
        /// <returns>pcks1格式的RSA私钥 base64格式</returns>
        public static string ConvertPrivateKeyPkcs8ToPcks1(string privateKey)
        {
            return Convert.ToBase64String(ConvertPrivateKeyPkcs8ToPcks1(Convert.FromBase64String(privateKey)));
        }
        /// <summary>
        /// 将pcks8格式的RSA私钥转化为pcks1格式
        /// </summary>
        /// <param name="privateKey">pcks8格式的RSA私钥</param>
        /// <returns>pcks1格式的RSA私钥</returns>
        public static byte[] ConvertPrivateKeyPkcs8ToPcks1(byte[] privateKey)
        {
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privateKey);
            PrivateKeyInfo pkInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
            return pkInfo.ParsePrivateKey().ToAsn1Object().GetEncoded();
        }
    }

测试代码如下:

        static void RSAPcksTransferDemo(int keyLength = 2048)
        {
            RsaKeyPairGenerator generator = new RsaKeyPairGenerator();
            generator.Init(new KeyGenerationParameters(new SecureRandom(), keyLength));
            var keyPair = generator.GenerateKeyPair();
            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
            var pcks8Private = Convert.ToBase64String(privateKeyInfo.ToAsn1Object().GetEncoded());
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
            var pcks8Public = Convert.ToBase64String(publicKeyInfo.ToAsn1Object().GetEncoded());
            var pcks1Private = RSAPcksTransferHelper.ConvertPrivateKeyPkcs8ToPcks1(pcks8Private);
            var pcks1Public = RSAPcksTransferHelper.ConvertPublicKeyPkcs8ToPcks1(pcks8Public);

            Console.WriteLine("pcks8Private == pcks1Private:{0}", pcks8Private == pcks1Private);
            Console.WriteLine("pcks8Public == pcks1Public:{0}", pcks8Public == pcks1Public);

            Func<byte[], string, int> func = (b, s) =>
            {
                for (var i = 1; i < 100; i++)
                {
                    if (Convert.ToBase64String(b.Skip(i).ToArray()) == s)
                        return i;
                }
                return 0;
            };
            //移除pcks8前部声明信息来生成pcks1
            var number = func(Convert.FromBase64String(pcks8Private), pcks1Private);
            if (number != 0)
            {
                //RSA秘钥不管keyLength为何值,始终固定返回26
                Console.WriteLine("pcks8Private need to remove prev {0} bytes", number);
                var pcks1PrivateWithRemove = Convert.ToBase64String(Convert.FromBase64String(pcks8Private).Skip(number).ToArray());
                Console.WriteLine("pcks1Private == pcks1PrivateWithRemove:{0}", pcks1Private == pcks1PrivateWithRemove);
            }
            number = func(Convert.FromBase64String(pcks8Public), pcks1Public);
            if (number != 0)
            {
                //RSA公钥受keyLength影响,1024时返回22,2048,3072,4096时返回24,当然RSA秘钥是以8增加长度的,所以可以通过循环1024+8来测试出22到24的改变规律
                Console.WriteLine("pcks8Public need to remove prev {0} bytes", number);
                var pcks1PublicWithRemove = Convert.ToBase64String(Convert.FromBase64String(pcks8Public).Skip(number).ToArray());
                Console.WriteLine("pcks1Public == pcks1PublicWithRemove:{0}", pcks1Public == pcks1PublicWithRemove);
            }
        }
注意测试代码里除了通过辅助类来进行转化外,还通过一种简单的方式,即直接通过移除pcks8的声明部分来达到生成pcks1的目的,测试结果如下:

私钥不管秘钥长度如何,始终移除pcks8格式最开始的26个byte

公钥受长度影响,在1024时移除pcks8格式最开始的22个byte,2048开始往后均为24个byte


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值