0

Given the key in pem format similar to

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DE1BB301BDE4BB45

msUEpZKZ0uaOmhGXBPnh2GoNSXyExdeqETd9w71l0G1bk1cCbiV4EOnmR7bcN+OE
(20 lines)
YoIx/E+tFHkt3gQcFhVUNgSOe/5+huXwRwUC5dthPzzZFlDCXHfwfrrBzOSGxZpX
uBs1JxY4qOLRdZVaZlQespForxBTYD6RuHi1UI5lqEW7363VyCLho9QYgGFM0LUi
qbln5WV37PTmayxMfzlGUB2XazwON+WU3obbXuCFXAy96Y6VGzv0lQ==
-----END RSA PRIVATE KEY-----

And the encrypted string(which was encrypted using the public key) I tried to decrypt with the following code

TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.IV = HextoByte("DE1BB301BDE4BB45");                
des.Padding = PaddingMode.None;
des.Mode = CipherMode.CBC;   
des.Key = Convert.FromBase64String(//Key from above from ms.. to ==);                                                                  
byte[] encrypted = Convert.FromBase64String("");
byte[] decrypted = des.CreateDecryptor().TransformFinalBlock(encrypt, 0, encrypt.Length);
string decryptedString = Encoding.UTF8.GetString(decrypted) 

Which results in exception when assigning the key "Specified key is not a valid size for this algorithm"

The Key was generated using (Also tried with 192)

openssl genrsa -des3 -out Key.pem 2048

Public key was generated using

openssl rsa -in Key.pem -pubout > Key.pub

Would anyone be able to help me to point out what I am missing or doing wrong?

Thank you

user3614386
  • 119
  • 1
  • 10

2 Answers2

0

The maximum size of the key for 3DES in C# is 192 bits. Please also see MSDN documentation here.

So you will want to make sure that Convert.FromBase64String() really returns 24 byte.

Please also have a look at the following questions / answers:

Community
  • 1
  • 1
Tobias Breuer
  • 825
  • 1
  • 11
  • 19
0

You are using an RSA key with a 3DES cipher. It's the wrong key.

The private key in your question has been encrypted with 3DES, probably using password-based encryption. You'll need the key in order to decrypt the private key before you can use it for anything.

Once you recover the RSA private key, most likely you will use it to decrypt symmetric keys. Normally, each encrypted message will include a symmetric cipher key, encrypted with the recipient's public key. That's what you'll be decrypting with the RSA private key that you recover.

Once you have the second symmetric key, you can use it to decrypt the actual message, as you show in your question.

In pseudo-code:

rsaPvtKey = passwordDecrypt(password, encryptedPrivateKey)
contentKey = rsaDecrypt(rsaPvtKey, encryptedContentKey)
message = tripleDesDecrypt(contentKey, encryptedMessage)

The code in the original question is pretty close. The problem is that the key is to be derived from the password, and the message is the base-64 encoded information. Successfully decrypting this will yield an RSA private key in PKCS #8 format, and .NET should have an API for loading that.

OpenSSL key derivation is not standard (and it's not very good). You'll need to find or write some code to create the DES-EDE3 key from your password using the MD5 hash algorithm.

d0 = md5(password || iv)        /* Hash password and IV */
d1 = md5(d0 || password || iv)  /* Hash first hash, password, and IV */
key = subarray(d0 || d1, 0, 24) /* Take the first 24 bytes of d0 + d1 */

The JavaScience code contains a function, GetOpenSSL3deskey to do this key derivation. You would call it with the iv you extracted, the password, a count of 1, and a miter of 2.

Once you do this, assign it to des.Key in your original code. What was assigned to des.Key should be assigned to encrypt instead. (This is what the DecodeOpenSSLPrivateKey function does.) When you complete the decryption, the byte array decrypted will contain the RSA private key in PKCS #1's Chinese Remainder Theorem format. There should be some .NET API to construct an RSA private key from this. (See the DecodeRSAPrivateKey function for this.)

This RSA private key can then be used to decrypt other messages.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • yes it is encrypted using a password. Do you know how to do that in .Net using native classes? – user3614386 Apr 30 '15 at 02:47
  • @user3614386 There are a lot of steps, and multiple ways to do each. What software was used to encrypt the message itself? – erickson Apr 30 '15 at 03:30
  • Would the steps be less, if this key was in another format? like how it is just a few lines of code if its pk8 format – user3614386 Apr 30 '15 at 03:36
  • @user3614386 Yes, you should be able to decrypt the key using `openssl` (use the `pkey` command without a `-` option, if I recall); that would eliminate the first step, which might involve non-standard openssl encryption formats. Is the message in a standard format like PGP or CMS (S/MIME)? – erickson Apr 30 '15 at 03:39
  • Message is a simple string which needs to be decrypted in c# which is encrypted using the key in pkcs8 format in Java. Java apparently can do this with native classes with a few lines of code. Amazed that c# requires many lines to do so. I can do this using http://www.jensign.com/opensslkey/opensslkey.cs but that runs through lot of playing with setting up RSA class with various parameters. I am expecting a simple load key with password and decrypt. – user3614386 Apr 30 '15 at 04:07
  • @user3614386 Please see my update. If you want simple, use the library that you linked. There's nothing built into .NET for this (or Java, either; you need something like the BouncyCastle library to handle OpenSSL's non-standard key derivation). – erickson Apr 30 '15 at 20:48
  • Thank you for the detailed explanation. While I probably would use extracts of the library to solve it, I understand the process much better. – user3614386 May 01 '15 at 03:52