2017-06-09 79 views
0

我有一個使用第三方支付門戶的在線電子商務網站。支付門戶網站工作正常,直到第三方支付門戶網站要求每個人開始使用具有其他支付參數的散列碼。Java to ruby​​ AES/ECB/PKCS5Padding加密

現在的問題是,第三方支付門戶網站只提供了一個用於實現散列鍵的頁面文檔。

這是所提供的文件: -

加密算法

爲了減輕參數回火/修改而傳送和數據的郵寄,商家可以加密使用由挪威電信POC提供的散列密鑰的請求。這個加密的請求與主要請求一起發送,然後在OPS端進行協調以檢測參數是否被更改。加密可以使用以下算法完成:

  1. Create map of all the fields that are part of the request 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. Get the list of field name from the map created in the first step

    List fieldNames = new ArrayList(fields.keySet());

  3. Sort the map fields based on map key in alphabetical order

    Collections.sort(fieldNames);

  4. Create a string in following format: amount=10&expiryDate=20150101151515&orderRefNum=11001&postBackURL= http://localhost:9081/local/status.php&storeId=28

  5. Use AES/ECB/PKCS5Padding algorithm to encrypt with the key and string produced in the previous step

    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(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

位置:類encryptDa TA

/tmp/java_Ramvov/encryptData.java:16:錯誤:找不到符號

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

符號:方法encodeBase64(字節[])

位置:類的Base64

2錯誤

任何幫助將不勝感激

我也有試圖重現此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)) 

但是生成的加密是通過支付門戶

+0

他們是否有示例輸出?所以你可以驗證你的執行的正確性 –

+0

@Srgio Tulentsev沒有提供任何東西。他們現在剛給我的另一個信息是最後一步中的「值」變量是這個字符串「amount = 10&expiryDate = 20150101151515&orderRefNum = 11001&postBackURL = http:// localhost:9081/local/status.php&storeId = 28」 –

+0

那麼,你怎麼能確定你正確實施了密碼?詢問他們的示例輸出。或者運行該java代碼。 –

回答

2

拒絕使用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是20150101 151515在Java代碼中,但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代碼?好吧,我懷疑ruby想要的方式與openssl相同,因爲ruby crypto通常在引擎蓋下使用openssl。所以關鍵定義改變爲

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

這現在打印:

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

其中除了換行符的位置是相同的其它兩個的輸出。希望您能夠與對方進行溝通,並記住:

使用ECB模式進行防篡改輸入非常愚蠢。

+0

此問題未能得到解決和解釋。謝謝@wallenborn –