Convert ruby to java

Converting JRuby RubyHash to Java Map?

I want to use JRuby to run some ruby scripts, get a result and continue using Java/Scala. Unfortunately, I don’t know how to convert an object from a RubyHash to a Java or Scala Map. Is there a simple way to do this? Any suggestions on how to do it?

Due to documentation it is java.util.Map so you can use either scala.collection.JavaConverters._ or implicite ones scala.collection.JavaConversions._ to covenrt to scala collections

3 Answers 3

class org.jruby.RubyHash implements java.util.Map , so, it already is a Java Map , albeit a non-generic «raw» type.

Unfortunately, JRuby’s Hash class only inherits the generic to_java method from Kernel , unlike Array which has its own version.

This doesn’t, although it looks like it should:

 < 'one' =>1, 'two' => 2 >.to_java(:string, :int) 
[It might be worthwhile filing this as a feature request.]

Appreciate the answer, however, I am looking into something that wouldn’t require me to change any existing ruby code.

You don’t have to change anything. JRuby’s RubyHash implements java.util.Map , therefore every Ruby Hash already is a Java Map . Now, if you want to have a typed generic Map , then you will have to do something, because with Ruby being dynamically typed, there is simply nothing JRuby can do about statically providing a more precise type than a raw Map (or alternatively a Map , which is more or less the same thing).

Читайте также:  What is python pandas

org.jruby.RubyHash implements java.util.Map in a way that it attempts to convert Ruby objects to Java with «normal» Map operations.

e.g. if you have a hash such as: < 'a' =>1, ‘b’ => 2 > which (internally) means you have RubyString keys mapped to RubyFixnum values in a hash instance, on the Java side hash.get(«a») will work fine and return 1 as a java.lang.Long

I would suggest to change your approach slightly: this would involve only changing the way you initialize objects in ruby, the rest should be transparent.

Instead of using pure Ruby hash objects ( o=Hash.new or o=<> ), please use instead java.util.HashMap like in this snippet:

require 'java' o = java.util.HashMap.new # you could also use o = Java::JavaUtil::HashMap.new 

From then on, o would be a java object used as a hash by Ruby code, and can still be accessed using java methods.

Another mode complete snippet:

>> require 'java' => true >> o = Java::JavaUtil::HashMap.new => <> >> o[1] = 2 => 2 >> o["cm"] = true => true >> p o.keys # ruby methods/interface [1, "cm"] => nil >> p o.keySet().to_a # java methods [1, "cm"] => nil 

Источник

Translating Ruby Encryption Code to Java

You need to use the IV and Key from your Java Example, not a new/random IV/Key:

require "openssl"
require "base64"
require 'byebug'

include Base64

plain_text = "abceeffslaj"

key = 'Bar12345Bar12345'
iv = 'RandomInitVector'

cipher = OpenSSL::Cipher::AES128.new(:CBC)
cipher.encrypt
cipher.key = key
cipher.iv = iv
cipher_text = cipher.update(plain_text) + cipher.final

cipher = OpenSSL::Cipher::AES128.new(:CBC)
cipher.decrypt
cipher.key = key
cipher.iv = iv
decrypted_plain_text = cipher.update(cipher_text) + cipher.final

puts "AES128 in CBC mode"
puts "Key: " + urlsafe_encode64(key)
puts "Iv: " + urlsafe_encode64(iv)
puts "Plain text: " + plain_text
puts "Cipher text: " + urlsafe_encode64(cipher_text)
puts "Decrypted plain text: " + decrypted_plain_text

Migrate String encryption from Ruby to Java

The first thing to do is to derive the IV and key from the given password.

From the link above, you will get an encoded IV and KEY that corresponds with «VDiJjncs4ak s9e42J3PpmQv8n5T8L3zzuFaGdrzK/wU» respectively.
This means that the key and IV vector used in the Java code are wrong as it was said in the comments.

Below is the resulting Java code:

public class SymmetricDESedeCipher private static final String DATA = "Whackabad"; 
private static final String ALGORITHM = "DESede";
private static final String XFORM = "DESede/CBC/PKCS5Padding";
private static final String KEY = "s9e42J3PpmQv8n5T8L3zzuFaGdrzK/wU";
private static final String IV = "VDiJjncs4ak Data: " + DATA);
System.out.println("Encrypted Data: " + new BASE64Encoder().encode(encBytes));
>
>
Data: Whackabad
Encrypted Data: AEsDXVcgh2jsTjlDgh+REg==

Convert Encrypt code in java to Ruby

def aes(key,string) 
cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
cipher.encrypt
cipher.padding = 1
cipher.key = hex_to_bin(Digest::SHA1.hexdigest('secret_key')[0..32])
cipher_text = cipher.update(string)
cipher_text return bin_to_hex(cipher_text).upcase
end
def aes_decrypt(key, encrypted) 
encrypted = hex_to_bin(encrypted.downcase)
cipher = OpenSSL::Cipher::Cipher.new("aes-128-cbc")
cipher.decrypt
cipher.padding = 1
cipher.key = hex_to_bin(Digest::SHA1.hexdigest('secret_key')[0..32])
d = cipher.update(encrypted)
d end

hex_to_bin and bin_to_hex

def hex_to_bin(str) 
[str].pack "H*"
end

def bin_to_hex(s)
s.unpack('C*').map< |b| "%02X" % b >.join('')
end

In My case, The java code was using default initialization vector, So I did not set any iv, Also, there was hex_to_bin was a missing piece there. So after that, all started working properly.

I hope it helps someone if they come across this issue.

Encrypt Ruby decrypt Java

The exact code that is produced by Ruby is not specified (which I would consider a bug), you can find the format by reading the source code, especially this part:

 blob = "#--#" 
blob = "#--#" if aead_mode?

Where the IV is a random IV, generated using Cipher::new of the openssl module.

Encrypt in Ruby and Decrypt in Java — Why is it not working?

This is the problem — or at least a problem:

byte[] result = cipher.doFinal(encryptedData);
return result.toString();

You’re calling toString() on a byte array. Arrays don’t override toString() . That won’t give you what you want at all — as you can see. Instead, you need to write something like:

return new String(result, "UTF-8");

. but you need to know what encoding was used to turn the original string into bytes before encryption. It’s not clear to me from the Ruby code what encoding is used, but if you can be explicit about it (ideally using UTF-8) it’ll make your life a lot easier.

In short, I suspect this problem has nothing to do with encryption at all — it has everything to do with converting text to bytes in Ruby and then converting the same sequence of bytes back into a string in Java.

Of course the encryption may be failing as well but that’s a different matter.

How to Encrypt data in ruby same as SecretKeySpec?

The following version outputs the same result as your Java code:

# crypt.rb
require 'base64'
require 'openssl'

payLoad = "phoneNumber=%2B917738995286&pin=5577"
encodedKey = "vPDkdTDrcygLPROzd1829A= amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28" | openssl enc -K 38394f5549545550524c334938483347 -aes-128-ecb -base64

Note that openssl takes the key as hexadecimal string, so 89OUITUPRL4I9H3G should be written as its ASCII sequence 38394f5549545550524c334938483347

r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCtVXeH
FBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXmaakr4klz
1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=

Let’s try to replicate that in Java. To do this, we have to change a few things in your code:

  1. Your expiryDate is 20150101 151515 in the Java code, but 20150101151515 everywhere else. So let’s standardize on 20150101151515
  2. Base64.encodeBase64() does not exist. Java 8 has Base64 encoding built-in, and the code should be Base64.getEncoder().encodeToString(data)
  3. The return type of that is already string so encryptedValue = new String(Base64. ) is unnecessary.
  4. Furthermore, you need to declare the type of encryptedValue before you can use it.

With all that, this compiles in Java 8:

import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class encryptData public static void main(String[] args) throws Exception
String data="amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28";
String key="89OUITUPRL3I8H3G";

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

byte[] plaintext = data.getBytes();
byte[] ciphertext = cipher.doFinal(plaintext);
String encryptedValue = Base64.getEncoder().encodeToString(ciphertext);

System.out.println(encryptedValue);
>
>

and prints (linebreaks added by me):

r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCtVXeH
FBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXmaakr4klz
1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=

Ok so far. What about ruby?

#!/usr/bin/ruby

require 'openssl'
require 'base64'

data = "amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28"

key = "89OUITUPRL4I9H3G"
cipher = OpenSSL::Cipher.new("AES-128-ECB")
cipher.encrypt()
cipher.key = key
crypt = cipher.update(data) + cipher.final

crypt_string = (Base64.encode64(crypt))
puts crypt_string
mp8WVhyUHFDqvJKaRXbYKbZT1920TNboRpFLUdPaYsWTkiQ2fhN/tCL6wvtI
B9/Mu08McaKTVIWYeQAfVR5XcUKdeQ+CBcJJRs5krLBjtjiMNlBUq9JpCUaC
0eclfDMaGTE+Z4XSafjPictWzTG/Ye+vkJWC23yxW1zSjBnYBfg=

Why is the ruby code not working? Well i suspect that ruby wants the key in the same way as openssl, because ruby crypto usually uses openssl under the hood. So change the key definition to

key = "38394f5549545550524c334938483347"
key = Convert ruby to java.pack('H*')
r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCt
VXeHFBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXm
aakr4klz1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=

which apart from linebreak positions is identical to the output of the other two. Hope you’ll be able to get communication with the other side right, and remember:

Using ECB mode for tamper-proofing input is very stupid.

Источник

Jruby-Convert RubyString to Java Char

Below is the code i am using to Convert from RubyString to Java Char.. Could you please suggest me better way where Jruby (automatically handles these kind of Type Error or some code in jruby to convert)

ruby_string="Raj" java.lang.String.new(col_value) col_value=str_obj.charAt(0) 

Are you just trying to get the first character of ruby_string? And what’s the broader purpose of what you’re trying to do?

No.. i was trying to convert above ruby_string(ruby_string) to Java Character to call java method which accepts java char as argument

1 Answer 1

First, JRuby behaves a little differently depending on whether you run it in 1.8 mode or 1.9 mode. With JRuby 1.7.0 and up, 1.9 is the default; with others, 1.8 is the default. To change the default, you pass either —1.8 or —1.9 to jruby on the command line.

In 1.8 mode, certain operations on strings, like getting the character at a single index, return numbers ( Fixnum s), whereas in 1.9 mode they always return strings. JRuby converts automatically between Ruby Fixnum s between 0 and 65535 and Java char s, so you can pass a 1.8-mode «character» value directly to a Java method that accepts a character; e.g.

str = 'foo' java_obj.methodThatTakesAChar(str[0]) 

In 1.9 mode, since str[0] is a single-character string, you have to convert its character to a number. You do this with the ord instance method:

str = 'foo' java_obj.methodThatTakesAChar(str[0].ord) 

Источник

Оцените статью