繁体   English   中英

Java到ruby的AES / ECB / PKCS5Padding加密

[英]Java to ruby AES/ECB/PKCS5Padding 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. 从第一步中创建的地图中获取字段名称列表

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

  3. 根据地图关键字按字母顺序对地图字段进行排序

    Collections.sort(fieldNames);

  4. 创建以下格式的字符串:amount = 10&expiryDate = 20150101151515&orderRefNum = 11001&postBackURL = http:// localhost:9081 / local / status.php&storeId = 28

  5. 使用AES / ECB / PKCS5Padding算法使用上一步中生成的密钥和字符串进行加密

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

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

    cipher.init(Cipher.ENCRYPT_MODE,secretKey);

    加密的值=新的String(Base64.encodeBase64(cipher.doFinal(value.getBytes())));

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

我打了第三方支付门户服务热线,他们仅对告诉我钥匙有帮助。

如果有人可以帮助我告诉我第5步的Ruby等效标准,我将不胜感激。 谢谢

刚刚尝试了在线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())));
^

符号:变量encryptedValue

位置:类cryptoData

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

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

符号:方法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))

但是生成的加密被付款门户拒绝

使用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上进行20150101151515
  2. Base64.encodeBase64()不存在。 Java 8内置了Base64编码,代码应为Base64.getEncoder().encodeToString(data)
  3. 该类型的返回类型已经是字符串,因此不需要encryptedValue = new String(Base64...)
  4. 此外,你需要声明的类型encryptedValue ,然后才能使用它。

有了这些,就可以在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与openssl一样需要密钥,因为ruby加密通常在幕后使用openssl。 因此将键定义更改为

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

现在打印:

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

除了换行符位置,它与其他两个输出相同。 希望您能够与另一边进行交流,并记住:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM