2011-12-22 102 views
3

我不得不在Rails中實施支付網關,但我之前沒有使用或看過(Westpac在澳大利亞的Payway,如果有人感興趣)。使用AES密碼塊鏈接在Rails中解密字符串

他們的文檔並不差,而且系統非常合乎邏輯,迄今爲止這已經非常痛苦(支付集成的奇蹟)。

問題在於,在付款直接發送到西太平洋銀行並且處理付款後,他們用一個大的加密參數重定向回我們的網站。這意味着我們要解密才能訪問實際參數。

這裏是西太平洋銀行的指導:

The parameters are encrypted using AES with Cipher Block Chaining, using PCKS-5 Padding. The decryption algorithm should be initialised with a 16 byte, zero-filled initialization vector, and should use your encryption key (which can be found on the Security page of PayWay Net Shopping Cart setup).

Before decryption, the parameters passed with the redirect will appear as follows:

EncryptedParameters=QzFtdn0%2B66KJV5L8ihbr6ofdmrkEQwqMXI3ayF7UpVlRheR7r5fA6 
    IqBszeKFoGSyR7c7J4YsXgaOergu5SWD%2FvL%2FzPSrZER9BS7mZGckriBrhYt%2FKMAbTSS8F 
    XR72gWJZsul9aGyGbFripp7XxE9NQHVMWCko0NlpWe7oZ0RBIgNpIZ3JojAfX7b1j%2F5ACJ79S 
    VeOIK80layBwCmIPOpB%2B%2BNI6krE0wekvkkLKF7CXilj5qITvmv%2FpMqwVDchv%2FUNMfCi 
    4uUA4igHGhaZDQcV8U%2BcYRO8dv%2FnqVbAjkNwBqxqN3UPNFz0Tt76%2BP7H48PDpU23c61eM 
    7mx%2FZh%2Few5Pd0WkiCwZVkSZoov97BWdnMIw5tOAiqHvAR3%2BnfmGsx 

西太平洋銀行沒有Rails的演示,但他們確實有PHP。這裏是PHP演示:

function decrypt_parameters($base64Key, $encryptedParametersText, $signatureText) 
{ 
    $key = base64_decode($base64Key); 
    $iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    $td = mcrypt_module_open('rijndael-128', '', 'cbc', ''); 

    // Decrypt the parameter text 
    mcrypt_generic_init($td, $key, $iv); 
    $parametersText = mdecrypt_generic($td, base64_decode($encryptedParametersText)); 
    $parametersText = pkcs5_unpad($parametersText); 
    mcrypt_generic_deinit($td); 
} 

這裏是我試過用Rails:

def Crypto.decrypt(encrypted_data, key, iv, cipher_type) 
    aes = OpenSSL::Cipher::Cipher.new(cipher_type) 
    aes.decrypt 
    aes.key = key 
    aes.iv = iv if iv != nil 
    aes.update(encrypted_data) + aes.final 
end 

iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 
key = Base64.decode64("mysecretkey") 
data = Base64.decode64("QzFtdn0%2B66KJV5L8ihbr6ofdmrkEQwqMXI3ayF7UpVlRheR7r5fA6 
    IqBszeKFoGSyR7c7J4YsXgaOergu5SWD%2FvL%2FzPSrZER9BS7mZGckriBrhYt%2FKMAbTSS8F 
    XR72gWJZsul9aGyGbFripp7XxE9NQHVMWCko0NlpWe7oZ0RBIgNpIZ3JojAfX7b1j%2F5ACJ79S 
    VeOIK80layBwCmIPOpB%2B%2BNI6krE0wekvkkLKF7CXilj5qITvmv%2FpMqwVDchv%2FUNMfCi 
    4uUA4igHGhaZDQcV8U%2BcYRO8dv%2FnqVbAjkNwBqxqN3UPNFz0Tt76%2BP7H48PDpU23c61eM 
    7mx%2FZh%2Few5Pd0WkiCwZVkSZoov97BWdnMIw5tOAiqHvAR3%2BnfmGsx") 

cleartext = Crypto.decrypt(data, key, iv, "AES-128-CBC") 

我簡單地傳遞在同一個初始化向量作爲PHP指出的,雖然我不確定這是正確的Rails。

在任何情況下,都提供密鑰,並且易於Base64解碼,加密參數也是如此。在一天結束的時候,我得到這個錯誤:

cipher.rb:21:in `final': wrong final block length (OpenSSL::Cipher::CipherError) 
from cipher.rb:21:in `decrypt' 
from cipher.rb:29:in `<main>' 

誠然,我不喜歡這個東西加密的深度,但我靠在牆上,沒有時間(儘管利息) 瞭解更多。

+0

那麼密文('encrypted_data')需要是16個字節長的倍數。你用base64解碼了輸入嗎?如果你已經這樣做了,你可以把這個代碼添加到問題中嗎? – vstm 2011-12-22 07:01:26

+0

當然,代碼已被添加。 – chexton 2011-12-22 07:07:07

+1

嗯我猜EncryptedParameter數據需要首先「URI未轉義」:'data = Base64.decode64(URI.unescape(「the string ..」))' – vstm 2011-12-22 07:10:33

回答

8

問題是,輸入數據另外是「URI轉義」,ruby的base64解碼器沒有「關心」無效的base64輸入(%沒有base64位),所以沒有發生錯誤。

的解決方案是編碼URI「UNESCAPE」的與URI.unescape

require 'uri' 

data = Base64.decode64(
    URI.unescape("QzFtdn0%2B66 ... Iw5tOAiqHvAR3%2BnfmGsx")) 

當然,如果從GET/POST參數接收到的輸入數據,輸入數據是最可能已經「未轉義「通過你的網絡堆棧 - 就像一個小心的注意事項(如果輸入數據中出現百分號%,則雙重unescape可能會導致問題)。

+0

在PHP中,解密不能正常工作,因爲沒有應用'urldecode()',任何方式都要感謝您的支持。 – 2015-07-21 07:32:03