在PHP和Java Android之间使用RSA解密数据问题

在PHP和Java Android之间使用RSA解密数据问题,java,php,android,rsa,phpseclib,Java,Php,Android,Rsa,Phpseclib,我使用PHP服务器加密一些数据,然后将其解密到Android设备上。 但当我尝试在Android设备端解密它时,我得到以下错误: javax.crypto.BadPaddingException:错误:0407106B:rsa 例程:RSA_padding_check_PKCS1_type_2:块类型不是02 当我在 Cipher.getInstance("RSA/ECB/PKCS1Padding"); 我正在使用PHPSeclips库对PHP服务器上的值进行加密,目前是github的最后一个

我使用PHP服务器加密一些数据,然后将其解密到Android设备上。 但当我尝试在Android设备端解密它时,我得到以下错误:

javax.crypto.BadPaddingException:错误:0407106B:rsa 例程:RSA_padding_check_PKCS1_type_2:块类型不是02

当我在

Cipher.getInstance("RSA/ECB/PKCS1Padding");
我正在使用PHPSeclips库对PHP服务器上的值进行加密,目前是github的最后一个版本,并进行签名。这一部分确实有效,因为已经在Javacard程序上被解码,所以错误实际上不属于这里

这是我在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;
    }
使用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;
    }
以及它在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);
}
更新7/3/14对于那些犯同样错误的人,我建议您查看以下页面:

事实上,这让我找到了正确的方法来发现问题所在

引发的错误表明解密密钥与用于加密它的密钥不匹配,因此我观察了用于此交换的每个公钥。因为我使用了1024个密钥大小,所以我正在解析输入消息模+公共指数,每个都具有相应的大小。我注意到,与Android设备上显示的模数相比,模数并没有完全接收到。所以这里有一个错误,Android在使用KeyPairGenerator对象生成密钥时默认使用2048密钥大小。只需手动将密钥大小设置为1024即可解决此问题

例如:

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();
希望对您有所帮助。

您可能需要定义“CRYPT\u RSA\u PKCS15\u COMPAT”,没错

以下注释块详细说明:


基本上,OpenSSL和非常有潜力的Java也实现了PKCS1v1.5,而phpseclib实现了PKCS1v2.1。PKCS1 v2.1修改了PKCS1样式的加密,以使用随机填充,因此没有两个密文是相同的。

Thx neubert,但正如我所怀疑的,错误不是由于PHP加密,而是由于Android方面的错误。过了好几个小时,我才明白为什么这不起作用。像往常一样,这个错误是个愚蠢的错误。。。我将编辑我的帖子,详细描述我的生活,这是什么原因?我也有同样的问题。这是一个密钥长度问题,Android是2048,后端是1024。你能分享一下你是如何使用。KeyPairGeneratorSpec上的setKeySize1024将密钥大小设置为1024的吗?对我来说不适用。我也有同样的问题。很抱歉回复太晚,我已经用工作代码更新了我的帖子,以生成密钥对。