Skip to content
Advertisement

“Value <br of type java.lang.String cannot be converted to JSONObject" – Android Studio

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!

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement