1

I am trying to convert some C# code into ruby. Here is a snippet of the C# code:

string Encrypt(string toEncrypt, string key) {
        byte[] keyArray;
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

        keyArray = UTF8Encoding.UTF8.GetBytes(key);

        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = tdes.CreateEncryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        return Convert.ToBase64String(resultArray, 0, resultArray.Length);

My biggest issue seems to be around getting the padding specification right.

Here is what I have so far...

  des = OpenSSL::Cipher::Cipher.new('des-ecb')
  des.encrypt # OpenSSL::PKCS7 has to passed in somewhere
  des.key = '--The Key--'
  update_value = des.update(val)
ar3
  • 3,883
  • 3
  • 21
  • 22
  • 1
    The C# code uses 3DES, the other code uses DES. – CodesInChaos May 28 '14 at 23:15
  • 2
    You should consider replacing the C# code by something secure. ECB mode is rather weak, UTF-8 encoding for keys is a bad idea as well, and no reason to use 3DES over AES. – CodesInChaos May 28 '14 at 23:15
  • Well, that's my comments gone :) – Maarten Bodewes May 28 '14 at 23:16
  • Yeah, if I could use something different I most certainly would...but this is an integration with a third party using this antiquated tech :-/ – ar3 May 28 '14 at 23:25
  • Update...I ran All of through all of the ciphers, and none of them are matching...so, I'm pretty sure it is because of the PKCS7 stuff – ar3 May 29 '14 at 00:07
  • Also, just for the record: http://stackoverflow.com/questions/4427477/encrypting-decrypting-3des-in-ruby is close...just need to figure out the padding I think – ar3 May 29 '14 at 03:41
  • Does your C# code always produce the same output for same inputs? I don't see an IV being set . . . – Neil Slater May 29 '14 at 06:41
  • 1
    ECB doesn't set an IV I didn't think, but yes it does. I have an update though...I'll post it as an answer! – ar3 May 29 '14 at 12:17
  • 2
    @NeilSlater ECB does not use an IV. The blocks are computed completely independent from one another, so there is no vector - and therefore no initialization vector either. That's also the reason why it is not cryptographically secure; the encrypted blocks can be matched against each other to find repetition. – Maarten Bodewes May 29 '14 at 12:32

2 Answers2

4

After running through all of the available OpenSSL ciphers and testing to see if any of the outputs resulted in the same encrypted string with no success, I then did the same thing, but this time passing in a padding integer (from 0 - 20), and iterated over all of the ciphers again.

This resulted in a success!

The final code:

def encrypt val
  des = OpenSSL::Cipher::Cipher.new 'DES-EDE3'
  des.encrypt
  des.padding = 1
  des.key = '--SecretKey--'
  update_value = des.update(val)
  up_final = update_value + des.final

  Base64.encode64(up_final).gsub(/\n/, "")
end

The biggest thing to note is the I had to remove the newline characters, and had to put in a padding of 1.

I'm still confused on the padding...but, wanted to update everyone on what I found in case someone runs into this in the future

:Update: The padding didn't matter after all...if you take out that line it still encrypts the same as if you had any number in there...the big difference I was missing was taking out the newlines

ar3
  • 3,883
  • 3
  • 21
  • 22
2

Try 'des-ede3-ecb' or just '3des' as names instead. 'des-ecb' is unlikely to return a triple DES cipher.

PKCS#7 is normally the default for OpenSSL, so you may not have to specify it.

Make sure that your character-encoding (UTF-8, compatible with ASCII for values up to 7F) and encoding (base 64) matches as well.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • The documentation seems to indicate that PKCS#5 is the default...and des-ede3-ecb as well as 3des are returning an unsupported cipher error. – ar3 May 28 '14 at 23:33
  • 'des3' is a supported cipher however...but alas, I'm confused on how to get the PKCS#7 padding – ar3 May 28 '14 at 23:37
  • does it encrypt if you supply it plaintext that cannot be divided by 8 (with regard to byte size)? – Maarten Bodewes May 29 '14 at 00:15
  • Sorry, cannot get ruby with Openssl support up and running here, needs a recompile or something. – Maarten Bodewes May 29 '14 at 00:33
  • Yeah it encrypts, but I am testing against the encrypted output from the C# code, and it just isn't matching – ar3 May 29 '14 at 03:38
  • And, I'm just passing plain text, so I have to append the 'final' on the end of the 'update' result – ar3 May 29 '14 at 03:39
  • Thanks for the help owl! Your answer led me to think differently about the problem, and attack it from a different angle. – ar3 May 29 '14 at 12:23