2011-12-22 105 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