So I am using Android Studio (Java), and I have to communicate with a website that I made using Apache (xampp). I put in a json object 3 variables. Two of them are strings and the other is a signature I made using the code on the website – https://developer.android.com/training/articles/keystore. The error “Value <br of type java.lang. String cannot be converted to JSONObject” shows when the jsonObjectRequest is made because of the signature variable (I say this because when I take it out, the code works, but I really need to send the signature). The signature is in byte so I tried to put it in a string variable but that didn’t work either. I don’t believe the error is in the PHP code. How can I fix this?
This is my code:
Android Studio:
KeyStore ks = null; byte[] signature = null; try { ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry entry = ks.getEntry(alias, null); if (!(entry instanceof KeyStore.PrivateKeyEntry)) { Log.w("DEBUG_EC", "Not an instance of a PrivateKeyEntry"); } Signature s = Signature.getInstance("SHA256withECDSA"); s.initSign(((KeyStore.PrivateKeyEntry) entry).getPrivateKey()); s.update(data.getBytes()); signature = s.sign(); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableEntryException | InvalidKeyException | SignatureException e) { e.printStackTrace(); } JSONObject object2 = new JSONObject(); try { object2.put("id", data); object2.put("key", key); object2.put("signature", signature); } catch (Exception e) { Log.d("ID_DEBUG","Error"); e.printStackTrace(); } JsonObjectRequest jsonObjectRequest2 = new JsonObjectRequest(Request.Method.POST, url, object2, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.d("ID_DEBUG","String Response : "+ response.toString()); try { String resultados = response.getString("result_text"); if(resultados.equals("missing parameters")){ Toast.makeText(getApplicationContext(), "Error!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(),"Sucess!", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { Log.d("ID_DEBUG","Error"); e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("ID_DEBUG", error.toString()); } }); queue.add(jsonObjectRequest2);
I decided to put part of the php code. PHP:
<?php function json_response($message = null, $code = 200) { // clear the old headers header_remove(); // set the actual code http_response_code($code); // set the header to make sure cache is forced header("Cache-Control: no-cache, no-store"); header("Pragma: no-cache"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past // treat this as json header('Content-Type: application/json'); $status = array( 200 => '200 OK', 400 => '400 Bad Request', 422 => 'Unprocessable Entity', 500 => '500 Internal Server Error' ); // ok, validation error, or failure header('Status: '.$status[$code]); // return the encoded json return json_encode($message,JSON_UNESCAPED_SLASHES); } if (empty($_POST)) { $_POST = json_decode(file_get_contents("php://input"), true) ? : []; } (some code ...) $res = array(); if(empty($_POST['key']) || empty($_POST['signature'])) { $res['result_code']=400; $res['result_text']='missing parameters'; echo json_response($res); } else { $key=$_POST['key']; $signature=$_POST['signature']; $pubkeyid = openssl_pkey_get_public($key); // state whether signature is okay or not $ok = openssl_verify($data, $signature, $pubkeyid); if ($ok == 1) { if($key != NULL || $signature != NULL){ (some code ...) $final_result = array(); $final_result['result_code']='200'; $final_result['result_text']='OK'; echo json_response($final_result); } } elseif ($ok == 0) { $res['result_code']=400; $res['result_text']='invalid signature'; echo json_response($res); } else { $res['result_code']=400; $res['result_text']='error checking signature'; echo json_response($res); } // free the key from memory openssl_free_key($pubkeyid); } } ?>
Advertisement
Answer
I found the solution, the problem really was because of the format of the key and signature.
Android Studio:
KeyStore ks = null; byte[] signature = null; try { ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry entry = ks.getEntry(alias, null); if (!(entry instanceof KeyStore.PrivateKeyEntry)) { Log.w("DEBUG_EC", "Not an instance of a PrivateKeyEntry"); } Signature s = Signature.getInstance("SHA256withECDSA"); s.initSign(((KeyStore.PrivateKeyEntry) entry).getPrivateKey()); s.update(data.getBytes()); signature = s.sign(); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableEntryException | InvalidKeyException | SignatureException e) { e.printStackTrace(); } JSONObject object2 = new JSONObject(); try { object2.put("id", data); object2.put("key", key); object2.put("signature", Base64.getEncoder().encodeToString(signature)); } catch (Exception e) { Log.d("ID_DEBUG","Error"); e.printStackTrace(); } JsonObjectRequest jsonObjectRequest2 = new JsonObjectRequest(Request.Method.POST, url, object2, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.d("ID_DEBUG","String Response : "+ response.toString()); try { String resultados = response.getString("result_text"); if(resultados.equals("missing parameters")){ Toast.makeText(getApplicationContext(), "Error!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(),"Sucess!", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { Log.d("ID_DEBUG","Error"); e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("ID_DEBUG", error.toString()); } }); queue.add(jsonObjectRequest2);
PHP:
<?php function json_response($message = null, $code = 200) { // clear the old headers header_remove(); // set the actual code http_response_code($code); // set the header to make sure cache is forced header("Cache-Control: no-cache, no-store"); header("Pragma: no-cache"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past // treat this as json header('Content-Type: application/json'); $status = array( 200 => '200 OK', 400 => '400 Bad Request', 422 => 'Unprocessable Entity', 500 => '500 Internal Server Error' ); // ok, validation error, or failure header('Status: '.$status[$code]); // return the encoded json return json_encode($message,JSON_UNESCAPED_SLASHES); } if (empty($_POST)) { $_POST = json_decode(file_get_contents("php://input"), true) ? : []; } (some code ...) $res = array(); if(empty($_POST['key']) || empty($_POST['signature'])) { $res['result_code']=400; $res['result_text']='missing parameters'; echo json_response($res); } else { $key=$_POST['key']; $signature=$_POST['signature']; $key = "-----BEGIN PUBLIC KEY-----n" . chunk_split($chave, 64, "n") . '-----END PUBLIC KEY-----'; $key = openssl_pkey_get_public($key); if ($key == false) { $res['result_code']=400; $res['result_text']='key error'; echo json_response($res); } // state whether signature is okay or not $ok = openssl_verify($data, base64_decode($signature), $key, OPENSSL_ALGO_SHA256); if ($ok == 1) { if($key != NULL || $signature != NULL){ (some code ...) $final_result = array(); $final_result['result_code']='200'; $final_result['result_text']='OK'; echo json_response($final_result); } } elseif ($ok == 0) { $res['result_code']=400; $res['result_text']='invalid signature'; echo json_response($res); } else { $res['result_code']=400; $res['result_text']='error checking signature'; echo json_response($res); } // free the key from memory openssl_free_key($pubkeyid); } } ?>
Thank you to everyone who tried to help!