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

版权声明:本文为starfd原创文章,转载请标明出处。 https://blog.csdn.net/starfd/article/details/79225057
对于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


猜你喜欢

转载自blog.csdn.net/starfd/article/details/79225057