解密PHP和Java的Andr​​oid问题之间使用RSA的数据 [英] Decrypt data using RSA between PHP and Java Android issue

查看:766
本文介绍了解密PHP和Java的Andr​​oid问题之间使用RSA的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using a PHP server to encrypt some data and then decrypt it to an Android device. But when I try to decrypt it on the Android device side, I get the following error :

javax.crypto.BadPaddingException:错误:0407106B:RSA
  套路:RSA_padding_check_PKCS1_type_2:块类型不是02

javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02

当我在

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

我使用加密库PHPSeclips(在此日期最后github上的版本),一个PHP服务器上的价值和签名也是如此。这部分做的实际工作,因为已经习惯了上一个Java卡程序去codeD这样的错误实际上并不属于这里。

I am encrypting the value on a PHP server using PHPSeclips Library (last github version at this date) and signing as well. This part does actually works because already used to be decoded on a Javacard program so the error does not actually belongs here.

这是我继续在Android端方式:

This is the way I proceed on Android side :

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()方法:

With the getPrivateKey() method :

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端加密的:

And how it's encrypted on PHP side :

//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);
}

UPDATE(14年7月3日)对于那些谁得到我,你推荐一下以下页面同样的错误:的 http://hustoknow.blogspot.ca/2013/01/rsa-block-type-is-not-02 -error.html

UPDATE (7/3/14) For those who get the same mistakes I recommand you look at the following page : http://hustoknow.blogspot.ca/2013/01/rsa-block-type-is-not-02-error.html

事实上,这把我放在正确的方式来发现什么问题了。

In fact this put me on the right way to discover what the issue was.

引发的错误告诉解密密钥不匹配用于加密的钥匙,所以我看过用于这个交换的每个公共密钥。因为我用1024密钥大小,我解析与每个相关大小的输入消息(模数+公用指数)。而且我注意到,弹性模量并没有比Android设备上显示一个完全接收。因此,这里是错误的,Android的默认使用2048密钥大小,当您使用密钥生成KeyPairGenerator对象。只是手动密钥大小设置为1024来解决此问题。

The error raised tells that the decryption key does not match the key used to encrypt it, so I've watched every Public Key used for this exchange. Because I used 1024 key size I was parsing the input message (modulus + public exponent) with relevant size of each. And I noticed that the modulus was not fully received compared to the one displayed on the Android device. So here is the mistake, Android by default use 2048 key size when you use KeyPairGenerator object for key generation. Just set manually the key size to 1024 fix this issue.

例如:

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_RSA_PKCS15_COMPAT',真)

下面的注释块阐述:

<一个href=\"https://github.com/phpseclib/phpseclib/blob/a8c2ff0fb013169193c649adab512cafef5068cf/phpseclib/Crypt/RSA.php#L2272\" rel=\"nofollow\">https://github.com/phpseclib/phpseclib/blob/a8c2ff0fb013169193c649adab512cafef5068cf/phpseclib/Crypt/RSA.php#L2272

基本上,OpenSSL的(并且相当有可能的Java太)实现PKCS#1 v1.5的,而phpseclib实现PKCS#1 v2.1中。 PKCS#1 v2.1中修改PKCS1风格加密,利用随机填充,所以没有两个密文的将永远是一样的。

Basically, OpenSSL (and quite potentially Java too) implements PKCS#1 v1.5 whereas phpseclib implements PKCS#1 v2.1. PKCS#1 v2.1 modifies PKCS1 style encryption to make use of randomized padding so no two ciphertext's will ever be the same.

这篇关于解密PHP和Java的Andr​​oid问题之间使用RSA的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆