RSA Шифрование данных между Android и сервером на PHP

322
05 декабря 2017, 22:18

Вообщем кругом враги, поэтому захотелось реализовать следующее:

  1. Генерация пары ключей на стороне Android (ок)
  2. Генерация пары ключей на стороне PHP (ок)
  3. Обмен ключами (ок)
  4. Зашифровать строку на стороне Android (ок)
  5. Расшифровать строку на стороне PHP (fail)

Вообщем уже 6 часов пытаюсь разобрать (чую соль на столе перед глазами, но не вижу вупор ее). Дошел я вот до чего:

  1. Генерю ключи на стороне Android
  2. шифрую строку публичным ключом
  3. шифрую еще одну строку в базе64
  4. передаю все это на сервер с PHP
  5. на сервере строка просто в base64 (расшифровывается - все ок)
  6. строку на сервере PHP удается зашифровать и расшифровать, используя ключи переданные из Андроид!
  7. Но строку зашифрованную в Андроид на стороне PHP расшифровать не выходит!

Код PHP

$resultTxt='<br> #################### <br> '; //собираем результат широфания

$pub=$_POST['pub'];             //передал публичный ключ
$priv=$_POST['priv'];           //передал приатный ключ
$data=$_POST['data'];           //передал строку закодированную в Android
$data2=$_POST['data2'];         //передал строку закаодированную в бейз
$pubkey= base64_decode($pub);   //публичный ключ декодирован из BASE64
$privkey=base64_decode($priv);  //приватный ключ декодирован из BASE64 (для теста)

//#### результат
$resultTxt.='';
$resultTxt.=' Из приложения данные: <br>';
$resultTxt.='<br>data (base64):'.$data;
$resultTxt.='<br><br>';
$resultTxt.='<br>pub :'.$pubkey;
$resultTxt.='<br>priv :'.$privkey;
$resultTxt.='<br>data :'.$data;
$resultTxt.='<br>data2 :'.$data2;
$resultTxt.='<br>data2 :'.base64_decode($data2);

$data= base64_decode(iconv("UTF-8","UTF-8",$data)); // это уже так, в бреду
$resultTxt.='<br>data decode 64 :'.base64_decode($data2);
openssl_private_decrypt($data, $decrypted2, $privkey);
$resultTxt.='<br>CRYPTED_DATA:'.$data;
$resultTxt.='<br>DECRYPTED_DATA : '.$decrypted2;
$resultTxt.='<br>### полученными данными зашифруем строку  на стронe PHP ###<br>';

openssl_public_encrypt("hel про драйв ddlo fd df d world 2", $crypted, $pubkey);//OPENSSL_PKCS1_PADDING, OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING, OPENSSL_NO_PADDING

$crypted= base64_encode($crypted);
$crypted= base64_decode($crypted);
openssl_private_decrypt($crypted, $decrypted, $privkey);
$resultTxt.='<br>CRYPTED TEST STRING: '.$crypted;
$resultTxt.='<br>DECRYPTED TEST STRING: '.$decrypted;

Код Java Android

  //Генерация ключей
 String alias = "someTxt-RSA";
 String []pairs = new String[2];
     try {
         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
         KeyPairGenerator kpg2 = KeyPairGenerator.getInstance("RSA", "BC"); //
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
kpg.initialize(2048,new SecureRandom()); //new SecureRandom()
KeyPair pair = kpg.generateKeyPair();
 privateKey=pair.getPrivate();
 publicKey=pair.getPublic();

PKCS8EncodedKeySpec keyspec = new KCS8EncodedKeySpec(pair.getPrivate().getEncoded());
                PKCS8EncodedKeySpec keyspecpub = new PKCS8EncodedKeySpec(pair.getPublic().getEncoded());
                byte[] arrByte =pair.getPrivate().getEncoded();
                byte[] arrByte2 =pair.getPublic().getEncoded();
                        StringBuilder sb = new StringBuilder();
                sb.append("-----BEGIN PRIVATE KEY-----"+" \n");
        //        byte[] arrByte = keyspec.getEncoded();
                sb.append(Base64.encodeToString(arrByte, Base64.DEFAULT));
                sb.append("-----END PRIVATE KEY-----");

                StringBuilder sb2 = new StringBuilder();
                sb2.append("-----BEGIN PUBLIC KEY-----"+" \n");
         //       byte[] arrByte2 = keyspecpub.getEncoded();
                sb2.append(Base64.encodeToString(arrByte2, Base64.DEFAULT));
                sb2.append("-----END PUBLIC KEY-----");

 String privKeyBase64=Base64.encodeToString(sb.toString().getBytes(), Base64.DEFAULT);
  String pubKeyBase64=Base64.encodeToString(sb2.toString().getBytes(), Base64.DEFAULT);

// шифруем строку JAVA
 byte[] encodedBytes = null;
 Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
            c.init(Cipher.ENCRYPT_MODE, privateKey);
             encodedBytes =theTestText.getBytes("UTF-8");

encodedBytes = c.doFinal(encodedBytes); String coded =Base64.encodeToString(encodedBytes, Base64.DEFAULT);

//отправляем на сервер PHP
String urlString = "http://mysite.com/myscript.php"; // URL to call
                String pub = pubKeyBase64; //data to post
                String priv = privKeyBase64; //data to post
                String data = params[0].getData("data"); //data to post
                try {
                String data2 =coded; //data to post
 OutputStream out = null;   
                    URL url = new URL(urlString);
                    HttpClient httpclient = new DefaultHttpClient();

                    HttpPost postMethod = new HttpPost(urlString);
                    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
                    //nameValuePairs.add(new BasicNameValuePair("ID_group", PageViewActivity.Get_list_group.get(PageViewActivity.Cur_group_position).get(0)));
                    nameValuePairs.add(new BasicNameValuePair("pub", pub));
                    nameValuePairs.add(new BasicNameValuePair("priv", priv));
                    nameValuePairs.add(new BasicNameValuePair("data", data));
                    nameValuePairs.add(new BasicNameValuePair("data2", data2));

     postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                   // postMethod.setEntity(nameValuePairs);
                    HttpResponse responseHttp = httpclient.execute(postMethod);
                    //System.out.println(response);
                    return EntityUtils.toString(responseHttp.getEntity());

Код немного сокращен.

Answer 1

Код на стороне андроид ничего не шифрует:

byte[] encodedBytes = null;
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
c.init(Cipher.ENCRYPT_MODE, privateKey);
encodedBytes = theTestText.getBytes("UTF-8"); // что это???
String coded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
// ...
String data2 = coded;

Но все таки, я бы рекомендовал вам использовать TLS. Мое объяснение в похожем ответе: Принцип работы открытого и закрытого ключа. Как сделать?

READ ALSO
Непонятки с doctrine

Непонятки с doctrine

Привет всем!

293
Как правильно вывести чекбокс ?

Как правильно вывести чекбокс ?

Доброго времени суток ! Есть форма в которой есть чекбокс, суть работы формы проста, она отправляет значение чекбокса в базу данныхСостояние...

236
Doctrine, как посчитать кол-во записей с join?

Doctrine, как посчитать кол-во записей с join?

Есть некий запрос на получение данных (запрос сокращен для удобства):

221
Зачем в PHP нужны фигурные скобки?

Зачем в PHP нужны фигурные скобки?

Какой смысл в данных фигурных скобках?

201