//----- Get the binary RSA PRIVATE key, decrypting if necessary ---- static byte[] DecodeOpenSSLPrivateKey(String instr) { const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; String pemstr = instr.Trim(); byte[] binkey; if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter)) { return(null); } StringBuilder sb = new StringBuilder(pemstr); sb.Replace(pemprivheader, ""); //remove headers/footers, if present sb.Replace(pemprivfooter, ""); String pvkstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace try { // if there are no PEM encryption info lines, this is an UNencrypted PEM private key binkey = Convert.FromBase64String(pvkstr); return(binkey); } catch (System.FormatException) { //if can't b64 decode, it must be an encrypted private key //Console.WriteLine("Not an unencrypted OpenSSL PEM private key"); } StringReader str = new StringReader(pvkstr); //-------- read PEM encryption info. lines and extract salt ----- if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED")) { return(null); } String saltline = str.ReadLine(); if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,")) { return(null); } String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim(); byte[] salt = new byte[saltstr.Length / 2]; for (int i = 0; i < salt.Length; i++) { salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16); } if (!(str.ReadLine() == "")) { return(null); } //------ remaining b64 data is encrypted RSA key ---- String encryptedstr = str.ReadToEnd(); try { //should have b64 encrypted RSA key now binkey = Convert.FromBase64String(encryptedstr); } catch (System.FormatException) { // bad b64 data. return(null); } //------ Get the 3DES 24 byte key using PDK used by OpenSSL ---- SecureString despswd = GetSecPswd("Enter password to derive 3DES key==>"); //Console.Write("\nEnter password to derive 3DES key: "); //String pswd = Console.ReadLine(); byte[] deskey = GetOpenSSL3deskey(salt, despswd, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes if (deskey == null) { return(null); } //showBytes("3DES key", deskey) ; //------ Decrypt the encrypted 3des-encrypted RSA private key ------ byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV if (rsakey != null) { return(rsakey); //we have a decrypted RSA private key } else { Console.WriteLine("Failed to decrypt RSA private key; probably wrong password."); return(null); } }