版权声明:本文为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