Внедрение RSA Publickey в Android
Я реализовал криптографию RSA, используя в php, javascript и android app, используя библиотеку:
phpseclib для стороны php
pidcrypt для JavaScript
версия bouncrycastle (bcprov-jdk14-151) для поставщика услуг Android
У меня есть мой криптографический механизм, такой как:
user->request->publickey
->server->generate(publickey,privatekey) and save private key into Database
->server->sendpublickey->user
->user->encryptdata->send->server->decrypt
Однако этот механизм прекрасно работает между Javascript и PHP шифрования и дешифрования, но на платформе Android, когда сервер отправляет открытый ключ. Он не может расшифровать открытый ключ.
Теперь я проверил другой сценарий для этого
PHP KeyGenerating
$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
define('CRYPT_RSA_EXPONENT', 65537);
extract($rsa->createKey(1024));
PHP DecryptingCode
$rsa = new Crypt_RSA();
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->loadKey($pri);
$binaryCiphertext=base64_decode($encrypted);
$strBase64DecryptedData=$rsa->decrypt($binaryCiphertext);
$plaintText = base64_decode($strBase64DecryptedData);
как мой открытый ключ.
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALrBdN8F83hT2+pBsAwiNx+v3FWp51IdEElE8UvVhfZYmePbitpzLcJi
jZ4/tvRFXJGhqa3PKPUQkH2F4VrHruA2kNceiL/Btywc9oM+tDMeX1jcRKwXwK1k
KdccKwn0qywG6YxQuqWQIotOfV+IIuhcHdaHBl6CZ05/cBo6AlMlAgMBAAE=
-----END RSA PUBLIC KEY-----
запросить ключ от сервера и сервера генерирует открытый ключ и закрытый ключ и отправить открытый ключ MODULUS и EXPONENT в приложение для Android и применить этот код:
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(mod,exp); KeyFactory keyFactory = KeyFactory.getInstance("RSA","BS"); PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec); Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BS"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(plaintText.getBytes()); byte[] encodedBytes = org.bouncycastle.util.encoders.Base64.encode(encryptedBytes); String encryptedData = new String(encodedBytes);
этот код не может расшифровать сообщение, и я получаю эту ошибку от PHP SIDE
Decryption error in /security/RSA.php on line **2493**
Код RSA.php 2493
if (ord($em[0]) != 0 || ord($em[1]) > 2) {
user_error('Decryption error');
return false;
}
Второй сценарий - получить строку открытого ключа и проанализировать ее.
byte[] keyBytes = Base64.decode(keyString, Base64.DEFAULT); String rsaPublicKeyString = new String(keyBytes); String sliceKeyHeader = rsaPublicKeyString.replaceAll("(-+BEGIN RSA PUBLIC KEY-+\\r?\\n|-+END RSA PUBLICKEY-+\\r?\\n?)", ""); byte[] encodedDER = Base64.encode(sliceKeyHeader.getBytes(),Base64.DEFAULT); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedDER); KeyFactory kf = KeyFactory.getInstance("RSA","BC"); PublicKey pkPublic = (PublicKey) kf.generatePublic(publicKeySpec);
с этим я получаю ошибку
java.security.spec.InvalidKeySpecException:
java.lang.ClassCastException: com.android.org.bouncycastle.asn1.DERApplicationSpecific
cannot be cast to com.android.org.bouncycastle.asn1.ASN1Sequence
Я знаю, что закодированный открытый ключ закодирован с помощью DER, но я все еще не знаю, что здесь делать. Думаю, кто-то может мне помочь с декодированием с помощью DER.
Третий сценарий
final Reader reader = new StringReader(rsaPublicKeyString); PemReader pemReader = new PemReader(reader); PemObject pemObject= pemReader.readPemObject(); pemReader.close(); AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(pemObject.getContent());
Я забыл ошибку, это было похоже
unable to cast pemObject to asymmetric ( not sure but something like that )
Я даже попробовал некоторые коды из ссылок ниже, но я получаю разные ошибки.
RSA Android Encrypt / RSA PHP расшифровывает PhpSeclib <-> BouncyCastle RSA
Пожалуйста, посмотрите в код и помогите мне.
1 ответ
ОК После нескольких часов работы с EXPONENT и MODULUS я успешно зашифровал и расшифровал данные между Android-приложением и PHP-сервером. Вот решение, которое может кому-то пригодиться
Моя ошибка заключалась в том, что когда шифрованные данные были готовы к кодированию, я использовал внутренний класс BASE64 JAVA, который генерирует закодированные данные размера x2, а php имеет другой механизм декодирования и кодирования (я не очень уверен в этом, просто предположение)
поэтому, чтобы аннулировать, что я использовал библиотеку APACHE commons-codec-1.8, вот правильный код
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(mod,exp);
KeyFactory keyFactory = KeyFactory.getInstance("RSA","BS");
PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BS");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));//
byte[] coded = Base64.encodeBase64(encryptedBytes); //used library encode decode
String encryptedData = new String(encodedBytes);
вторая последняя строка должна была зашифровать двоичные данные в BASE64
Я узнаю больше о различиях BASE64 между JAVA и PHP
Спасибо