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, e.g.,:
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.
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, e.g.,:
...
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();
...