0

There is a payment gateway that I'm working on, and they have a Java demo that is working however I want to implement this in php instead.

The payment gateway encrypt the payload by using 3DES with a random generated key. That key was encrypted with RSA by using the payment gateway's PUBLIC key.

The problem is when I use the php script to do RSA encryption on that key, the payment gateway isn't can't extract the key correctly and apparently the RSA encryption on the PHP wasn't working correctly...

Here's the Java version of the RSA encryption:

public static byte[] encrypt(byte[] data, String pubKey64) {

    try {
         byte[] key = Toolkit.base64Decode(pubKey64);
         KeyFactory rsaKeyFac = KeyFactory.getInstance("RSA");
         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
         RSAPublicKey pbk = (RSAPublicKey) rsaKeyFac.generatePublic(keySpec);
         System.out.println("MODE:"+Cipher.ENCRYPT_MODE);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, pbk);

        byte[] encDate = cipher.doFinal(data);
        return encDate;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

And here what's I came out with at the PHP script:

use phpseclib\Crypt\RSA as RSA;




$PUB_KEY = '-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ1fKGMV/yOUnY1ysFCk0yPP4bfOolC/nTAyHmoser+1yzeLtyYsfitYonFIsXBKoAYwSAhNE+ZSdXZs4A5zt4EKoU+T3IoByCoKgvpCuOx8rgIAqC3O/95pGb9n6rKHR2sz5EPT0aBUUDAB2FJYjA9Sy+kURxa52EOtRKolSmEwIDAQAB
-----END PUBLIC KEY-----';

$PAYLOAD = 'b78850d2f35108b4bc4e7a41';

function encrypt($key,$payload){
    $rsa = new RSA();
    $rsa->loadKey($key); // public key

    $rsa->setEncryptionMode(2);
    $ciphertext = $rsa->encrypt($payload);

    return base64_encode($ciphertext);
}

The Java version was using PKCSPADDING so I set the mode on phpseclib to 2 which is PKCSPADDING but still it won't work. Am I missing anything? Can anyone please point it out for me?

UPDATE:

Not sure if this is the reason that causing it but I removed the "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY ----" portion and it worked.

Thanks for everyone's help.

3
  • 2
    Almost everything about this sounds so wrong you might want to reconsider using that payment gateway. Commented Dec 17, 2016 at 16:25
  • I'm with pvg. Removing those lines shouldn't have made a difference. I tried loading your key as you posted it and doing echo $rsa and got the same key as the one you posted. I also tried removing the lines you said you remoed and got the same key when I did that too. So it doesn't seem like removing those lines is changing the key. PKCS1 padding is randomized so it almost seems like maybe the payment gateway just isn't able to correctly accommodate all the possible bytes that could be randomly selected.. Commented Dec 17, 2016 at 23:49
  • It could be, I know the gateway isn't using the best technique on their end but we don't really have any choice to begin with. But regardless of what, really appreciate the help and feedback! Commented Dec 19, 2016 at 20:54

1 Answer 1

1

Try doing define('CRYPT_RSA_PKCS15_COMPAT', true); before you start the encryption process.

Quoting phpseclib 2.0's RSA.php:

/**
 * RSAES-PKCS1-V1_5-DECRYPT
 *
 * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
 *
 * For compatibility purposes, this function departs slightly from the description given in RFC3447.
 * The reason being that RFC2313#section-8.1 (PKCS#1 v1.5) states that ciphertext's encrypted by the
 * private key should have the second byte set to either 0 or 1 and that ciphertext's encrypted by the
 * public key should have the second byte set to 2.  In RFC3447 (PKCS#1 v2.1), the second byte is supposed
 * to be 2 regardless of which key is used.  For compatibility purposes, we'll just check to make sure the
 * second byte is 2 or less.  If it is, we'll accept the decrypted string as valid.
 *
 * As a consequence of this, a private key encrypted ciphertext produced with \phpseclib\Crypt\RSA may not decrypt
 * with a strictly PKCS#1 v1.5 compliant RSA implementation.  Public key encrypted ciphertext's should but
 * not private key encrypted ciphertext's.
 *
 * @access private
 * @param string $c
 * @return string
 */
Sign up to request clarification or add additional context in comments.

1 Comment

upvoting your answer as it might helps other although I didn't try this out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.