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!