简体   繁体   中英

Get public key from private key in Bouncy Castle C#

So I have an encrypted private key PEM. I can read it and get the private key with the following:

AsymmetricKeyParameter key;
using (var sr = new StringReader(pem))
using (var pf = new PassowrdFinder { Password = password })
{
  var reader = new PemReader(sr, pf);
  key = (AsymmetricKeyParameter)reader.ReadObject();
}

I also need the public key, to create the SPKI later on. I tried

var keyPair = new AsymmetricCipherKeyPair(key, key);

Which fails with System.ArgumentException: Expected a public key Parameter name: publicParameter .

My question is: How to get the public key from a private key?

I'm a little clumsy with the Bouncycastle C# library but I think the way to do this is to explicitly make a new key object using the appropriate components of the private key. Example

// Make an rsa keypair for testing

var rand = new SecureRandom();
var keyGenParams = new RsaKeyGenerationParameters(
        new BigInteger("65537"), rand, 1024, 64
    );
var rsaKeyGen = new RsaKeyPairGenerator();
rsaKeyGen.Init(keyGenParams);
var rsaKeyPair = rsaKeyGen.GenerateKeyPair();
var rsaPriv = (RsaPrivateCrtKeyParameters)rsaKeyPair.Private;

// Make a public from the private

var rsaPub = new RsaKeyParameters(false, rsaPriv.Modulus, rsaPriv.PublicExponent);

// Try it out

var rsaKeyPair2 = new AsymmetricCipherKeyPair(rsaPub, rsaPriv);

The downside of this approach is that it requires a concrete instance of a specific kind of asymmetric key; it does not work with the abstract asymmetric key classes.

It should be very simple:

AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)reader.ReadObject();

Then:

var pubKey = KeyPair.public;

Thanks to help from James K Polk, here is what I came up with

    AsymmetricCipherKeyPair GetKeyPairFromPrivateKey(AsymmetricKeyParameter privateKey)
    {
        AsymmetricCipherKeyPair keyPair = null;
        if (privateKey is RsaPrivateCrtKeyParameters rsa)
        {
            var pub = new RsaKeyParameters(false, rsa.Modulus, rsa.PublicExponent);
            keyPair = new AsymmetricCipherKeyPair(pub, privateKey);
        }
        else if (privateKey is Ed25519PrivateKeyParameters ed)
        {
            var pub = ed.GeneratePublicKey();
            keyPair = new AsymmetricCipherKeyPair(pub, privateKey);
        }
        else if (privateKey is ECPrivateKeyParameters ec)
        {
            var q = ec.Parameters.G.Multiply(ec.D);
            var pub = new ECPublicKeyParameters(ec.AlgorithmName, q, ec.PublicKeyParamSet);
            keyPair = new AsymmetricCipherKeyPair(pub, ec);
        }
        if (keyPair == null)
            throw new NotSupportedException($"The key type {privateKey.GetType().Name} is not supported.");

        return keyPair;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM