简体   繁体   中英

C# BouncyCastle EC Private Key Export Using PemWriter

I'm generating an EC key pair in C# BouncyCastle and trying to export the private key in a PEM file using the PemWriter. The code for doing so is as follows:

var ecKeyPairGenerator = new ECKeyPairGenerator();
CKeyGenerationParameters ecKeyGenParams = new ECKeyGenerationParameters(SecObjectIdentifiers.SecP384r1, new SecureRandom());
ecKeyPairGenerator.Init(ecKeyGenParams);
AsymmetricCipherKeyPair pair = ecKeyPairGenerator.GenerateKeyPair();

string path = @"c:\tmp\test\myprivkey.pem";
TextWriter textWriter = new StreamWriter(path);
PemWriter pemWriter = new PemWriter(textWriter);
// passing pair results in the private key being written out
pemWriter.WriteObject(pair);
pemWriter.Writer.Flush();
pemWriter.Writer.Close();

An example output from the snippet above is:

-----BEGIN EC PRIVATE KEY-----
MD4CAQEEMJvNXtTUd7A/fY/9/LSXM+Xb/6QS7GydeART/OieN3zh23Uuy0tgiS1D
rohXMgiPvqAHBgUrgQQAIg==
-----END EC PRIVATE KEY-----

However, when doing the same thing using 'openssl' and the same EC curve (secp384r1), the resulting PEM file is quite different, eg,:

openssl ecparam -name secp384r1 -genkey -out mykey2.pem -noout

-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDBqCE9+AWL56cvR2/tRNdyaTIlJnfr6TbhCG+Q48w6yyKR+hE0jkeOV
7yh1t8NwqT6gBwYFK4EEACKhZANiAAS2uLv7KG6RRBZBOecaxBz8FsMobnxgZkbQ
8cKdL1DRym1lUDwgfX8AxOC6qkuD1k0UekpHcwiy1mSghy4640qBAKcR3mVghMVF
77Nm8x6nwNijWZroeqhjrw268PPPuAw=
-----END EC PRIVATE KEY-----

As you can see, the key length is very different, and the P12 file I create with the former doesn't get imported into the Windows cert stores. I must be doing something wrong with C# BouncyCastle but can't see what (looking at the source code of the PemWriter and other related classes doesn't point to any obvious errors).

Any help would be greatly appreciated. Thanks.

A little late to the party, you could write the private and public key explicitly (maybe it is better to use a separate file):

...
// passing pair results in the private key being written out
pemWriter.WriteObject(pair.Private);
pemWriter.WriteObject(pair.Public);
pemWriter.Writer.Flush();
pemWriter.Writer.Close();

However, the current Version of Bouncy Castle (1.8.5) already writes the public key into the (private key) PEM file. So you should not need to write the public key explicitly.

Additionally, both of the following lines are basically the same:

 pemWriter.WriteObject(pair);
 pemWriter.WriteObject(pair.Private);

as can be seen in the sourcecode:

# .../BouncyCastle/.../MiscPemGenerator.cs
private static PemObject CreatePemObject(...)
{
  ...
  if (obj is AsymmetricCipherKeyPair)
    return MiscPemGenerator.CreatePemObject((object)
      ((AsymmetricCipherKeyPair) obj).Private,
      algorithm, password, random);
  ...
}

It turns out you can create an instance of ECPrivateKeyStructure with both private and public keys and save the Base64-encoded string of the object to file, eg,:

...
int orderBitLength = privKeyParam.Parameters.N.BitLength;
X962Parameters x962 = new X962Parameters(privKeyParam.PublicKeyParamSet);
ECPrivateKeyStructure privKeyStruct = 
                    new ECPrivateKeyStructure(orderBitLength, privKeyParam.D, pubKeyInfo.PublicKeyData, x962);

string header = @"-----BEGIN EC PRIVATE KEY-----";
string privKeyStr = Convert.ToBase64String(privKeyStruct.GetDerEncoded(), 
                    Base64FormattingOptions.InsertLineBreaks);
string tail = @"-----END EC PRIVATE KEY-----";

string path = @"c:\tmp\myprivkey.pem";
TextWriter textWriter = new StreamWriter(path);
textWriter.WriteLine(header);
textWriter.WriteLine(privKeyStr);
textWriter.WriteLine(tail);
textWriter.Flush();
textWriter.Close();
...

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