question

klangan avatar image
klangan asked ·

Getting Crypto Failure response in sandbox

Does anyone have a working PERL example:

No matter what I post to /v2/merchant/{mId}/pay I always get the same failure message:
{"paymentId":"TXK3B3WE0KP5M","result":"DECLINED","failureMessage":"CRYPTO FAILURE"}

I've scoured forums on encrypting the card number correctly and believe that I've done it right, but always get the crypto failure response:

Is there any documentation that provides examples of values we can use to make sure we are doing the encryption correctly?

I'm working in Perl, retrieving the Public Key from the pem provided (two different methods produce the same result, so I'm pretty sure I'm doing that step correctly:
use MIME::Base64 qw( encode_base64 );
use Crypt::OpenSSL::RSA;
use Crypt::OpenSSL::Bignum;
use Digest::SHA1 qw(sha1 sha1_hex sha1_base64); #tried them all

my $n = Crypt::OpenSSL::Bignum->new_from_decimal($keys->{modulus});
my $e = Crypt::OpenSSL::Bignum->new_from_decimal($keys->{exponent});
my $rsa_pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e);
# $rsa_pubkey consistently returns the same value.

# prepend the prefix to the cardnumber. Clover docs say this cardnumber should return success.
my $string = "$keys->{prefix}4264281511117771";

#encrypt them
my $cipher = sha1($rsa_pubkey,$string);

# and finally encode them to base64
my $encryptednumber = encode_base64($cipher,"");

Always get Crypto Failure.

Anybody have any ideas what I could be doing wrong???

thanks in advance for any help on this.
Payments
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Raymond Lee avatar image
Raymond Lee answered ·
Hi @klangan,

After looking over your code again, one thing I missed is that you generated a public key correctly, but afterwards you only did a SHA1 hash on the public key + the plaintext. You still need to perform an RSA encryption on the plaintext, using encrypt($string). Looking at the doc for Crypt::OpenSSL::RSA, it already uses SHA1 hashing to do the encryption (if you look under use_sha1_hash), so you do not need to use Digest::SHA1 at all.

From your code, try:
my $rsa_pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($n, $e);
my $string = "$keys->{prefix}4264281511117771";
my $string_UTF8 = encode_utf8($string); # Just in case, but can try without.
my $cipher = $rsa_pubkey->encrypt($string_UTF8);
my $encryptednumber = encode_base64($cipher);

Hope that helps,

Raymond

1 comment Share
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Thank you Raymon, that did the trick. Much obliged.

1 Like 1 · ·
klangan avatar image
klangan answered ·
Thanks so much for the suggestion Raymond

Sadly that didn't make a difference and I tried every permutation I can think of.
Tried encoding the string
Tried decoding the string and then encoding the string
Tried the same things on the public key as well.

also, regardless of whether or not the string is encoded/decoded the cipher comes out the same. I'd expect that if the original strings weren't in utf-8 and the encoding them to uft-8, that I'd end up with a slightly different cipher.

In otherwords:
my $cipher = sha1($rsa_pubkey,$string);
my $cipher2 = sha1($rsa_pubkey,$string_UTF8);
my $cipher3 = sha1($rsa_pubkey_UTF8,$string_UTF8);

all return the same result.

Always the same CRYPTO FAILURE message.

So stuck on this and so much time trying to figure this out :(


Share
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Raymond Lee avatar image
Raymond Lee answered ·
One thing I would check is that your SHA1 encryption is done on a UTF-8 character encoded string, as a UTF-8 string is expected during the decryption process.

Looking at the perldoc for Digest::SHA (which Digest::SHA1 is derived from), it states it silently converts UTF-8 strings to native encoding (most likely ISO-8859-1). Therefore I recommend encoding your string as UTF-8 bytes, then encrypt that directly.

Here is a stackoverflow answer that shows how to do that. You can use:
my $bytes = encode_utf8($string);
which is the equivalent of:
my $bytes = encode("utf8", $string)

Share
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Welcome to the
Clover Developer Community