Intro
I am working on converting a Java library to .Net.
The library is an implementation of polymorphic pseudonym decryption and will be used in The Netherlands to decrypt "BSNk"s in the area of European eIDAS electronic identification services.
I have already converted most of the library and worked with the author of the Java version to verify the results. The next step is to make the .Net library actually usable for Dutch companies, and that's where I have been stuck for the past 2 weeks.
The algorithms use an elliptic curve in a PEM file as one of the parts for the calculation. But the clients (the users of the library) will receive this in the form of a p7 and a p8 file which you can convert/extract/decode (?) to the PEM data.
Question
How can I get from te p7+p8 files to a PEM string in C#?
Preferably using just System.Security.Cryptography.Pkcs, but I currently am using BouncyCastle in other parts (because the Java version did). Not listed below but I did also try to do this using SignedCms and EnvelopedCms, but got nothing but (to me) incomprehensible errors from that. I don't have a lot of experience in cryptography, but have learned quite a bit over the past few weeks.
If I understand it correctly than I would explain this as the p7 file being the envelope of the PEM message, and the envelope is signed/encrypted using the private key in the p8 file?
Code
public static string ConvertToPem(string p7File, string p8File)
{
var p7Data = File.ReadAllBytes(p7File);
var p8Data = File.ReadAllBytes(p8File);
// Java version gets the private key like this:
// KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(bytesArray));
var privateKey = PrivateKeyFactory.CreateKey(p8Data);
var parser = new CmsEnvelopedDataParser(p7Data);
var recipients = parser.GetRecipientInfos().GetRecipients().OfType<RecipientInformation>();
var recipientInformation = recipients.First();
//Java version gets the message like this:
//final byte[] message = keyInfo.getContent(new JceKeyTransEnvelopedRecipient(key).setProvider("BC"));
var keyInfo = (KeyTransRecipientInformation)recipientInformation;
var message = keyInfo.GetContent(privateKey);
return Encoding.ASCII.GetString(message);
}
Update 8-10-2018 Following a tip from the author of the Java library I tried to skip the problem of automatically converting to PEM and just using openssl to decrypt it. Unfortunately the openssl command to decrypt the files also fails! Both on Windows as well as on Linux. The strange this is that this is done using the same files that work perfectly fine when used in the Java library. Is the p8 corrupt? Is it somehow only compatible when used in the Java JceKeyTransEnvelopedRecipient???
openssl cms -decrypt -inform DER -in dv_keys_ID_D_oin.p7 -inkey privatep8.key -out id.pem
(I also tried using PEM instead of DER but to no avail. The files are in the GitHub repo)
Update 9-10-2018 Thanks to Carl who figured out the cause of the seemingly corrupt p8 file. Instead of directly decrypting it using openssl cms we had to convert the binary DER p8 to a base64 encoded PEM first.
openssl pkcs8 -inform der -outform pem -in private.p8 -out private-p8.pem -topk8 -nocrypt
We could also do this in c# by reading the bytes from the p8 file, converting them to Base64 and adding the BEGIN/END PRIVATE KEY header/footer around it.
Resources
You can see this code being used and failing as a unit test in my project. The project also includes matching p7, p8 and PEM files to test with.
The Java version can be found here: https://github.com/BramvanPelt/PPDecryption
My work in progress version can be found here: https://github.com/MartijnKooij/PolymorphicPseudonymisation