Внедрение RSA Publickey в Android


Я реализовал криптографию RSA с использованием php, javascript и приложений для Android с использованием библиотеки:

  1. Phpseclib для php-стороны

  2. Pidcrypt для javascript

  3. Версия Bouncrycastle(bcprov-jdk14-151) для поставщика услуг anrdroid

У меня есть свой криптографический механизм, такой как:

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

$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

$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-----
  1. Запрашивает ключ у сервера, а сервер генерирует открытый и закрытый ключи и отправляет открытый ключ МОДУЛЬ и ПОКАЗАТЕЛЬ СТЕПЕНИ в приложение для 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

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;
 }
  1. Второй сценарий заключается в получении строки открытого ключа и ее анализе

    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 encode decode ---

  1. Третий сценарий

     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 Шифрование /RSA PHP расшифровка phpseclib <-> RSA для вышибалы

Пожалуйста, загляните в код и помогите мне.

Author: Community, 2014-09-15

1 answers

ОК После нескольких часов работы с ПОКАЗАТЕЛЕМ и МОДУЛЕМ Я успешно зашифровал и расшифровал данные между приложением Android и сервером php . Вот решение, которое может кому-то пригодиться

Моя ошибка заключалась в том, что, когда данные шифрования готовы к кодированию, я использовал JAVA внутренний класс BASE64, который генерирует данные в кодировке размером 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

Спасибо

 2
Author: Asif Bakht, 2014-09-15 15:03:13