Я использую сервер PHP для шифрования некоторых данных, а затем расшифровываю их на устройстве Android. Но когда я пытаюсь расшифровать его на стороне устройства Android, я получаю следующую ошибку:
javax.crypto.BadPaddingException: ошибка: 0407106B: подпрограммы rsa: RSA_padding_check_PKCS1_type_2: тип блока не 02
Когда я нахожусь
Cipher.getInstance("RSA/ECB/PKCS1Padding");
Я шифрую значение на сервере PHP, используя библиотеку PHPSeclips (последняя версия 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) Тем, кто повторяет те же ошибки, я рекомендую посмотреть следующую страницу: http://hustoknow.blogspot.ca/2013/01/rsa-block-type-is-not-02-error.html
На самом деле это поставило меня на правильный путь, чтобы узнать, в чем проблема.
Возникшая ошибка говорит о том, что ключ дешифрования не соответствует ключу, используемому для его шифрования, поэтому я просмотрел каждый открытый ключ, используемый для этого обмена. Поскольку я использовал размер ключа 1024, я анализировал входное сообщение (модуль + общедоступная экспонента) с соответствующим размером каждого. И я заметил, что модуль не был получен полностью по сравнению с тем, который отображается на устройстве Android. Итак, вот ошибка, Android по умолчанию использует размер ключа 2048, когда вы используете объект KeyPairGenerator для генерации ключа. Просто установите вручную размер ключа на 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();
Надеюсь, это поможет.