PHP转Ruby实现SHA512哈希签名结果不一致求助
Fixing SHA512 Signature Mismatch Between PHP and Ruby
Let's break down why your Ruby code isn't matching the PHP signature, and fix it step by step:
Key Differences Causing Mismatch
- Hash Algorithm Choice: PHP uses a plain SHA-512 hash of the concatenated query string + secret, but your Ruby code incorrectly uses HMAC-SHA512—this is a distinct algorithm that treats the secret as a cryptographic key instead of just appending it to the input string.
- Query String Encoding: PHP's
http_build_queryconverts spaces to+by default, while Ruby's nativeto_queryconverts spaces to%20. This subtle difference changes the raw input to the hash function, resulting in completely different signatures.
Corrected Ruby Code
require 'digest' require 'uri' secret = '70b49742-adbf-4ac5-9cd6-5ded5c39aa83' fields = { 'merchant_reference' => '1234567890', 'currency' => 'USD', 'amount' => '100.00', 'customer_ip'=> '123.123.123.123', 'customer_name' => 'Someone Buying', 'customer_address'=> '1, Bay Street', 'customer_phone' => '0123123123', 'customer_email' => 'someone@gmail.com', 'customer_country' => 'US', 'return_url' => 'https://demo.shop.com/payment/return' } # 1. Sort fields by key to match PHP's ksort behavior sorted_fields = fields.sort.to_h # 2. Generate query string that matches PHP's http_build_query output # URI.encode_www_form handles proper URL encoding, then replace %20 with + to match PHP's default space handling query_string = URI.encode_www_form(sorted_fields).gsub('%20', '+') # 3. Concatenate query string with secret, then compute plain SHA512 hash sign = Digest::SHA512.hexdigest(query_string + secret) puts sign # This will output your expected PHP signature
Explanation of Changes
- Swapped HMAC for Plain SHA512: We use
Digest::SHA512.hexdigestinstead ofOpenSSL::HMAC.hexdigestto mirror PHP'shash('SHA512', ...)behavior—this just hashes the raw concatenated string, no key-based HMAC logic involved. - Fixed Encoding Discrepancy:
URI.encode_www_formproperly encodes key-value pairs, then we replace%20with+to replicate how PHP handles spaces in query strings by default. - Sorted Fields Correctly:
fields.sort.to_hsorts the hash by key names in ascending order, which is exactly what PHP'sksortfunction does.
Running this code will produce the expected signature: 750b059c76657abf2a2b73e0c8d919ec5739f83a713fcdce1fd22f2b3f45446d554bc26d6508972ba16cf2c4e55ec46861d966ba976effaeba9802b829164417
内容的提问来源于stack exchange,提问作者user3206743
相关产品推荐
相关产品推荐

