Last active
November 25, 2016 17:35
-
-
Save enoliglesias/7d01a443700f9bb94752 to your computer and use it in GitHub Desktop.
Ds_Signature creation for Sermepa with SHA256
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def confirmation(credentials) | |
return false if params['ds_signature'].blank? | |
# The DES3-CBC key generation it's the same that in the creation gist | |
# You can take a look at the explanation | |
secret_key = credentials[:secret_key] | |
secret_key_base64 = Base64.strict_decode64(secret_key) | |
des3 = OpenSSL::Cipher::Cipher.new('des-ede3-cbc') | |
block_length = 8 | |
des3.padding = 0 | |
des3.encrypt | |
des3.key = secret_key_base64 | |
order_number = params["ds_order"] | |
order_number += "\0" until order_number.bytesize % block_length == 0 | |
key_des3 = des3.update(order_number) + des3.final | |
# params["ds_merchantparameters"] it's the merchant parameters json in base64 | |
# So, we don't need to encrypt again. We can use it directly :) | |
result = OpenSSL::HMAC.digest('sha256', key_des3, params["ds_merchantparameters"]) | |
# Here is the new 'magic' for Sermepa | |
# We MUST replace '+' with '-' | |
# We MUST replace '/' with '_' | |
# Maybe they use this signature in some GET route, or something like that | |
# And they return it with this characters replaced | |
sig = Base64.strict_encode64(result).gsub("+", "-").gsub("/", "_") | |
sig == params['ds_signature'] | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def sermepa_signature | |
# By default OpenSSL generates an all-zero array for the encriptation vector | |
# You can read it here: http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-iv-3D | |
# If you want to declare it, you can take a look at the next couple of lines | |
#bytes = Array.new(8,0) | |
#iv = bytes.map(&:chr).join | |
# We need to decode the secret key | |
key = Base64.strict_decode64("COMERCE SECRET KEY") | |
# In thee cipher initialization we need to speficy the encryptation like method-length-mode (http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-c-new). | |
# Sermepa needs DES3 in CBC mode | |
# The direct way the declare it's: des-ede3-cbc | |
# You can also declare like 'des3' wich use CBC mode by default | |
des3 = OpenSSL::Cipher::Cipher.new('des-ede3-cbc') | |
# OpenSSL use by default PKCS padding. But Sermepa (mcrypt_encrypt PHP function) use zero padding. | |
# OpenSSL do not allow zero padding. So we need to disable the default padding and make zero padding by hand | |
# Padding in cryptography is to fill the data with especial characteres in order to use the data in blocks of N (https://en.wikipedia.org/wiki/Padding_(cryptography)) | |
# We need to use blocks of 8 bytes | |
block_length = 8 | |
# We tell OpenSSL not to pad | |
des3.padding = 0 | |
# We want to encrypt | |
des3.encrypt | |
# Key set | |
des3.key = key | |
#des3.iv = iv | |
order_number = "YOUR Ds_Merchant_Order" | |
# Here is the 'magic'. Instead use the default OpenSSL padding (PKCS). We fill with \0 till the data have | |
# a multiple of the block size (8, 16, 24...) | |
order_number += "\0" until order_number.bytesize % block_length == 0 | |
# For example: the string "123456789" will be transform in "123456789\x00\x00\x00\x00\x00\x00\x00" | |
# data must be in blocks of 8 or the update will break | |
key_des3 = des3.update(order_number) + des3.final | |
# The next step is to encrypt in SHA256 the resulting des3 key with the base64 json | |
result = OpenSSL::HMAC.digest('sha256', key_des3, "YOUR MERCHANT PARAMETERS JSON IN BASE64") | |
# The last step is to encode the data in base64 | |
Base64.strict_encode64(result) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment