Java to ruby​​ AES / ECB / PKCS5Padding加密

时间:2017-06-09 10:33:48

标签: java ruby encryption

我有一个使用第三方付款门户网站的在线电子商务网站。支付门户网站运行正常,直到第三方支付门户网站要求所有人开始使用带有其他支付参数的哈希密钥。

现在问题是第三方支付门户网站只提供了一个用于实现哈希密钥的页面文档。

这是提供的文件: -

加密算法

为了在传输和发布数据时减轻参数回火/修改,商家可以使用Telenor POC提供的哈希密钥加密请求。该加密请求与主请求一起发送,然后主请求在OPS端协调以检测参数是否被改变。加密可以使用以下算法完成:

  
      
  1. 创建作为请求一部分的所有字段的地图   Map fields = new HashMap();

         

    fields.put(“amount”,“10”);

         

    fields.put(“storeId”,“28”);

         

    fields.put(“orderRefNum”,“11001”);

         

    fields.put(“expiryDate”,“20150101 151515”);

         

    fields.put(“postBackURL”,“http://localhost:9081/local/status.php”);

  2.   
  3. 从第一步中创建的地图中获取字段名称列表

         

    列出fieldNames = new ArrayList(fields.keySet());

  4.   
  5. 按字母顺序基于地图键对地图字段进行排序

         

    Collections.sort(FIELDNAMES);

  6.   
  7. 按以下格式创建字符串:    量= 10安培; expiryDate = 20150101151515&安培; orderRefNum = 11001&安培;一项PostBackUrl = http://localhost:9081/local/status.php&storeId=28

  8.   
  9. 使用AES / ECB / PKCS5Padding算法加密上一步生成的密钥和字符串

         

    Cipher cipher = Cipher.getInstance(“AES / ECB / PKCS5Padding”);

         

    SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(),“AES”);

         

    cipher.init(Cipher.ENCRYPT_MODE,secretKey);

         

    encryptedValue = new   串(Base64.encodeBase64(cipher.doFinal(value.getBytes())));

  10.   

现在另一个问题是我没有任何Java经验。

我打电话给第三方支付门户帮助热线,他们只是很有帮助告诉我密钥。

如果有人能够提供足够的帮助,告诉我Ruby的等同于第5步,我将不胜感激。感谢

刚试过在线java编译器提供的代码: -

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) {

    String data="amount=10&expiryDate=20150101 151515&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);
    encryptedValue = new String(Base64.encodeBase64(cipher.doFinal(data.getBytes())));
  }
}

这是错误: -

/tmp/java_Ramvov/encryptData.java:16:错误:找不到符号

encryptedValue = new String(Base64.encodeBase64(cipher.doFinal(data.getBytes())));
^

symbol:variable encryptedValue

location:class encryptData

/tmp/java_Ramvov/encryptData.java:16:错误:找不到符号

encryptedValue = new String(Base64.encodeBase64(cipher.doFinal(data.getBytes())));
                                  ^

symbol:method encodeBase64(byte [])

位置:类Base64

2个错误

任何帮助将不胜感激

我也尝试在ruby中重现这个java代码: -

data = "amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28"                                                                                                                                            
cipher = OpenSSL::Cipher.new("AES-128-ECB")
cipher.encrypt()
cipher.key = "89OUITUPRL4I9H3G"
crypt = cipher.update(data) + cipher.final()
crypt_string = (Base64.encode64(crypt))

但支付门户网站拒绝生成的加密

1 个答案:

答案 0 :(得分:3)

使用ECB模式进行防篡改输入非常愚蠢。

说完了,并且知道这不是你的错,因为首先不是你的想法,而你只是想让代码工作,让我们请一个独立的团队给我们一个参考点:

echo -n "amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL=http://localhost:9081/local/status.php&storeId=28" | openssl enc -K 38394f5549545550524c334938483347 -aes-128-ecb -base64

请注意,openssl将密钥作为十六进制字符串,因此89OUITUPRL4I9H3G应写为其ASCII序列38394f5549545550524c334938483347

输出结果为:

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

让我们尝试在Java中复制它。为此,我们必须在代码中更改一些内容:

  1. 您的expiryDate在Java代码中为20150101 151515,但在其他任何地方都为20150101151515。所以让我们在20150101151515
  2. 上进行标准化
  3. Base64.encodeBase64()不存在。 Java 8内置Base64编码,代码应为Base64.getEncoder().encodeToString(data)
  4. 返回类型已经是字符串,因此不需要encryptedValue = new String(Base64...)
  5. 此外,您需要在使用之前声明encryptedValue的类型。
  6. 尽管如此,这在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);
      }
    }
    

    和打印(我添加的换行符):

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

    好到目前为止。红宝石怎么样?

    #!/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=
    

    为什么ruby代码不起作用?我怀疑ruby想要的密钥与openssl一样,因为ruby crypto通常在引擎盖下使用openssl。因此,将键定义更改为

    key = "38394f5549545550524c334938483347"
    key = [key].pack('H*')
    

    现在打印:

    r7N11xE4HdbJyTByiTDifI1vifvZyNcNfKF+Jo7jEq4rN7c3EiOJxdWOUlCt
    VXeHFBTdPSROSmTkUTWfAuOQnHWqe/q/Msd1ykUDIz9eP5L6X6RI0R5UtUXm
    aakr4klz1kxEJOjR/WJ5xgd2clBh4iLcYi3caDrCkbD0kRDLQE4=
    

    除了换行符位置与其他两个位置的输出相同。希望你能够正确地与对方沟通,并记住:

    使用ECB模式进行防篡改输入非常愚蠢。