Mark
Mark

Reputation: 326

Bouncy Castle C# - PrivateKeyFactory.CreateKey 'Unknown object in GetInstance'

I have a sample C# script that handle decryption. By using the key provided with the sample, the code is working fine:

public static string DecryptByPrivateKey(string s, string key)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());

            engine.Init(false, GetPrivateKeyParameter(key));
            byte[] byteData = Convert.FromBase64String(s);
            var resultData = engine.ProcessBlock(byteData, 0, byteData.Length);
            return CommonHelper.EncodeBase64(resultData);
        }

private static AsymmetricKeyParameter GetPrivateKeyParameter(string s)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] privateInfoByte = Convert.FromBase64String(s);            
            AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);
            return priKey;
        }

However, when using our own private key, above function will throw exception at PrivateKeyFactory.CreateKey():

System.ArgumentException: 'Unknown object in GetInstance: Org.BouncyCastle.Asn1.DerInteger Parameter name: obj'

Our public/private key strings are generated with openssl on windows with command line:

openssl pkcs12 -in cert.pfx -nocerts -nodes -out cert.key
openssl rsa -in cert.key -out cert_private.key
openssl rsa -in cert.key -pubout -out cert_public.key

The key strings are in base64 format. The sample private key have 1624 characters while our private key has 1592 only.

In Visual Studio debug mode I checked the parameter privateInfoByte is a "byte[1192]". I have no clue on the error.

I am not sure my key strings are in correct format. How can I verify? Thank you.

Upvotes: 1

Views: 3780

Answers (1)

Topaco
Topaco

Reputation: 49390

According to the documentation, PrivateKeyFactory.CreateKey() expects a private key in PKCS#8 format. However, cert_private.key has the PKCS#1 format, which is thus incompatible.

cert.key, on the other hand, contains among other things the private key in PKCS#8 format, which can be extracted from this. Alternatively, the PKCS#1 formatted key can be converted to a PKCS#8 formatted key using OpenSSL, see openssl pkcs8:

openssl pkcs8 -topk8 -nocrypt -in <pkcs#1 key file> -out <pkcs#8 key file>

cert_private.key and cert.key contain the PEM encoded keys consisting of header, footer and the Base64 encoding of the DER encoded keys.
PrivateKeyFactory.CreateKey() expects a DER encoded key, i.e. from the PEM encoded key determined e.g. from cert.key, header, footer and line breaks are to be removed and the rest has to be Base64 decoded (which seems to be already considered in your code).
Header/footer of the PEM encoded PKCS#8 key are -----BEGIN PRIVATE KEY-----/-----END PRIVATE KEY----- and of the PEM encoded PKCS#1 key -----BEGIN RSA PRIVATE KEY----- / -----END RSA PRIVATE KEY-----.


Edit:

The statement openssl pkcs12 -out... -in... parses a PKCS#12 file and writes the contained certificates and private keys PEM encoded to a file. -nocerts causes the contained certificates not to be written, -nodes causes the private keys not to be encrypted (i.e. your statement exports only the PEM encoded private key unencrypted). The format of the exported private key is not explicitly specified, but can be easily identified as PKCS#8 using header/footer or an ASN.1 parser.

The statement openssl rsa -in... -out... finally exports the PKCS#8 formatted key to a PKCS#1 formatted key (PEM encoded). So to get the needed PKCS#8 formatted key you have the option to 1st use the PKCS#8 formatted key exported directly from the PKCS#12 file (s. previous section) or 2nd convert the PKCS#1 formatted key back to a PKCS#8 formatted key.

Therefore: yes, cert.pfx is a file in PKCS#12 format, and yes, cert_private.key is a key in PKCS#1 format, which is incompatible with PrivateKeyFactory.CreateKey(), which requires a key in PKCS#8 format.

Upvotes: 1

Related Questions