Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cipher "des-ede" working differently between JRuby and MRI #931

Closed
andrenpaes opened this issue Jul 31, 2013 · 4 comments
Closed

Cipher "des-ede" working differently between JRuby and MRI #931

andrenpaes opened this issue Jul 31, 2013 · 4 comments
Assignees
Milestone

Comments

@andrenpaes
Copy link

I'm facing a problem trying to decrypt some data using JRuby. I'm using the 'des-ede' cipher with no padding. The code works fine in MRI.

Here's an example:

require 'openssl'
require 'base64'

str = 'helloooo'
key = "WVqcvjGqaD7XBVBlXYbJYw==\n"

%w(des-ede des-ecb des-cbc).each do |cipher_method|
  des = OpenSSL::Cipher::Cipher.new(cipher_method)
  des.encrypt
  des.key = Base64.decode64(key)
  des.padding = 0
  data = des.update(str) + des.final
  enc = Base64.encode64(data)

  des = OpenSSL::Cipher::Cipher.new(cipher_method)
  des.decrypt
  des.key = Base64.decode64(key)
  des.padding = 0
  dec = des.update(Base64.decode64(enc)) + des.final

  puts cipher_method
  puts "'#{str}'"
  puts "'#{enc}'"
  puts "'#{dec}'"
  puts '------------'
end

Here's the output in JRuby (1.7.[3,4]):

$ jruby des-ede_test.rb 
des-ede
'helloooo'
'Nm3bZL1NQug=
'
'helloooo'
------------
des-ecb
'helloooo'
'Nm3bZL1NQug=
'
'helloooo'
------------
des-cbc
'helloooo'
'Nm3bZL1NQug=
'
'helloooo'
------------

Here's the output in MRI (1.9.2-p290 and ruby 1.9.3p327):

des-ede
'helloooo'
'7r9gHRoTpGs=
'
'helloooo'
------------
des-ecb
'helloooo'
'Nm3bZL1NQug=
'
'helloooo'
------------
des-cbc
'helloooo'
'Nm3bZL1NQug=
'
'helloooo'
------------

Is this a problem, or is it not possible to use 'des-ede' on JRuby? It seems weird that des-ede has the same output of des-cbc
Here's the description from 'des-ede' in OpenSSL: Two key triple DES EDE in ECB mode

@andrenpaes
Copy link
Author

Maybe this can help you guys. Here's the Java code that implements OpenSSL's des-ede:

@Test
public void testDESede() throws Exception {
    String str = "helloooo";
    byte[] originalKey = Base64.decodeBase64("WVqcvjGqaD7XBVBlXYbJYw==\n");

    byte[] key = new byte[24];
    System.arraycopy(originalKey, 0, key, 0, 16);
    // We're trying to use Two Key key (8 bytes each = 16 bytes), but java DESede only take 24 byte keys.
    // We need to repeat the first 8 bytes on the end of the key, to make a 24 bytes Two key
    // http://tripoverit.blogspot.com.br/2009/06/tripledes-encryption-compatibility.html
    System.arraycopy(originalKey, 0, key, 16, 8);

    final SecretKey secretKey = new SecretKeySpec(key, "DESede"); 
    String enc = encrypt(str.getBytes(), secretKey, "DESede/ECB/NoPadding");
    String dec = new String(Base64.decodeBase64(decrypt(Base64.decodeBase64(enc), secretKey, "DESede/ECB/NoPadding")));

    System.out.println(str);
    System.out.println(enc);
    System.out.println(dec);
    assertEquals(str, dec);
    // MRI Result for same key and input
    assertEquals("7r9gHRoTpGs=", enc);
}

private Cipher createCipher(String transformation) throws Exception {
    Cipher cipher = Cipher.getInstance(transformation);
    return cipher;
}

private String encrypt(byte[] data, Key secretKey, String transformation) throws Exception {
    Cipher cipher = createCipher(transformation);
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(cipher.update(data));
    baos.write(cipher.doFinal());
    String dec = Base64.encodeBase64String(baos.toByteArray());
    return dec;
}

private String decrypt(byte[] data, Key secretKey, String transformation) throws Exception {
    Cipher cipher = createCipher(transformation);
    cipher.init(Cipher.DECRYPT_MODE, secretKey);

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(cipher.update(data));
    baos.write(cipher.doFinal());
    return Base64.encodeBase64String(baos.toByteArray());
}

Here's the output, which is consistent with MRI:

helloooo
7r9gHRoTpGs=
helloooo

@skarger
Copy link

skarger commented Nov 1, 2013

I'm seeing a similar issue. The test below is like the one provided by @andrenpaes except that I'm using des-ede-cbc and leaving padding at its default.
Padding doesn't seem to matter; I see different results between MRI and JRuby when setting padding to 0 as well, just with shorter output values.

$ cat test.rb
require 'openssl'

cipher = OpenSSL::Cipher.new('des-ede-cbc')
cipher.encrypt
input = 'abcdefgh'
cipher.key = '16_byte_string_k'
cipher.iv = 'xxxxxxxx'

encrypted = cipher.update(input) + cipher.final
hex_representation = encrypted.unpack("H*")
puts "#{hex_representation}"

$ ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-darwin12.4.0]
$ ruby test.rb
["23ff779e88e2dbe1c009dc3105d8ff88"]

$ ruby -v
jruby 1.7.6 (1.9.3p392) 2013-10-22 6004147 on Java HotSpot(TM) 64-Bit Server VM 1.6.0_65-b14-462-11M4609 [darwin-x86_64]
$ ruby test.rb
["a5cfc96485d7203eb929c28ceb9fcd53"]

@adrian-gomez
Copy link

I'm having the same issue, i implemented the solution presented by @andrenpaes but that only worked for des-ede encryption/decryption for des-ede-cbc it only works for strings equal or shorter than 16 characters. If the data is longer it breaks again, that makes sense as i i'm using the same java cipher for 2 different ruby ciphers

MRI:
Input: 2542353435323330
Output: a89a25f603e7e98d

Input:: 25423534353233303035353132323731
Output: a89a25f603e7e98da4866975974e3dd3

Java
Input: 2542353435323330
Output: a89a25f603e7e98d

Input:: 25423534353233303035353132323731
Output: a89a25f603e7e98d0ef11d751c101d7c

While there is no fix for this, maybe @andrenpaes can help me get a java sample code that works for des-ede-cbc.

kares added a commit to jruby/jruby-openssl that referenced this issue Mar 20, 2015
@kares kares self-assigned this Mar 20, 2015
@kares
Copy link
Member

kares commented Apr 10, 2015

should be fine on jruby-openssl master (expected to land in 0.9.7), you can test a "snapshot" gem from https://oss.sonatype.org/content/repositories/snapshots/rubygems/jruby-openssl/0.9.7.dev-SNAPSHOT/ just make sure it's a snapshot released after Apr 08 2015

@kares kares closed this as completed Apr 10, 2015
@enebo enebo added this to the Non-Release milestone Apr 28, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants