Descriptografar dados usando o RSA entre problema PHP e Java Android

Estou usando um servidor PHP para criptografar alguns dados e descriptografá-los em um dispositivo Android. Mas quando tento descriptografá-lo no lado do dispositivo Android, recebo o seguinte erro:

javax.crypto.BadPaddingException: erro: 0407106B: rotinas rsa: RSA_padding_check_PKCS1_type_2: o tipo de bloco não é 02

Quando eu estou

Cipher.getInstance("RSA/ECB/PKCS1Padding");

Estou criptografando o valor em um servidor PHP usando a PHPSeclips Library (última versão do github nesta data) e assinando também. Esta parte realmente funciona porque já era decodificada em um programa Javacard, portanto, o erro não pertence aqui.

É assim que procuro no lado do Android:

protected byte[] decryptData(String alias, byte[] data) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, BadPaddingException, IllegalBlockSizeException, UnsupportedOperationException {
        Log.i(TAG, "decryptData() Decrypt data " + HexStringConverter.byteArrayToHexString(data));
        byte[] decryptedData = null;
        PrivateKey privateKey = getPrivateKey(alias);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        decryptedData = cipher.doFinal(data);
        Log.i(TAG, "decryptData() Decrypted data: " + HexStringConverter.byteArrayToHexString(decryptedData));
        return decryptedData;
    }

Com o método getPrivateKey ():

protected RSAPrivateKey getPrivateKey(String alias) {
        try {
            KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
            ks.load(null);
            KeyStore.Entry entry = ks.getEntry(alias, null);
            if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
                Log.w(TAG, "getPrivateKey() Not an instance of a PrivateKeyEntry");
            }
            return (RSAPrivateKey) ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
        } catch (NoSuchAlgorithmException e) {
            Log.w(TAG, "getPrivateKey() ", e);
        } catch (KeyStoreException e) {
            Log.w(TAG, "getPrivateKey() ", e);
        } catch (CertificateException e) {
            Log.w(TAG, "getPrivateKey() ", e);
        } catch (IOException e) {
            Log.w(TAG, "getPrivateKey() ", e);
        } catch (UnrecoverableEntryException e) {
            Log.w(TAG, "getPrivateKey() ", e);
        }
        return null;
    }

E como é criptografado no lado do PHP:

//Function for encrypting with RSA
function rsa_encrypt($string, $key)
{
    require_once(__DIR__ . '/../phpseclib/Crypt/RSA.php');
    //Create an instance of the RSA cypher and load the key into it
    $cipher = new Crypt_RSA();
    $cipher->loadKey($key);
    //Set the encryption mode
    $cipher->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    //Return the encrypted version
    return $cipher->encrypt($string);
}

//Function for decrypting with RSA 
function rsa_sign($string, $key)
{
    require_once(__DIR__ . '/../phpseclib/Crypt/RSA.php');
    //Create an instance of the RSA cypher and load the key into it
    $cipher = new Crypt_RSA();
    $cipher->loadKey($key);
    //Set the signature mode
    $cipher->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);

    //Return the signed message
    return $cipher->sign($string);
}

ATUALIZAÇÃO (3/7/14) Para aqueles que cometerem os mesmos erros, recomendo que você veja a seguinte página:http://hustoknow.blogspot.ca/2013/01/rsa-block-type-is-not-02-error.html

De fato, isso me colocou no caminho certo para descobrir qual era o problema.

O erro gerado informa que a chave de descriptografia não corresponde à chave usada para criptografá-la. Por isso, observei todas as Chaves Públicas usadas para essa troca. Como usei o tamanho da chave 1024, estava analisando a mensagem de entrada (módulo + expoente público) com o tamanho relevante de cada uma. E notei que o módulo não foi totalmente recebido em comparação com o exibido no dispositivo Android. Então, aqui está o erro: o Android, por padrão, usa o tamanho da chave 2048 quando você usa o objeto KeyPairGenerator para geração de chave. Basta definir manualmente o tamanho da chave como 1024 para corrigir esse problema.

Exemplo:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
            Calendar notBefore = Calendar.getInstance();
            Calendar notAfter = Calendar.getInstance();
            notAfter.add(Calendar.YEAR, 1);
            KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(mContext)
                    .setAlias(alias)
                    .setKeySize(1024)
                    .setSubject(
                            new X500Principal(String.format("CN=%s, OU=%s", alias,
                                    mContext.getPackageName())))
                    .setSerialNumber(BigInteger.ONE).setStartDate(notBefore.getTime())
                    .setEndDate(notAfter.getTime()).build();

            keyPairGenerator.initialize(spec);
            KeyPair kp = keyPairGenerator.generateKeyPair();

Espero que esta ajuda.

questionAnswers(1)

yourAnswerToTheQuestion