0

I'm developing desktop software with JavaFX and Java Spark which is basically a barebones framework for developing web apps, but I'm trying to use it strictly to put/get sensitive methods and variables on a server so that users can't access them. REST seems to be the correct approach but I'm struggling to understand 2 interrelated REST concepts. The Spark docs are light but I've integrated the few good tutorials into a working demo below but I've hit a wall. I'll briefly explain:

With the help of Postman I've been able to put a few records onto the server by using a path of http://localhost:4567/secrets and Body of:

{
      "title" : "demofield1",
    "content" : "12345"
}

Each record contains a title as an identifier (demofield1) and content as the sensitive data that should remain hidden from users at all times (12345). It's pretty trivial to put these strings onto a server and then get them by using title as a parameter, shown below. The demo code simply has a Model class for creating and returning a record (secret), a JSON conversion method, and a get and put Spark method. Secrets are stored locally in a HashMap for now, I'm assuming a real app would simply swap in a server DB.

The get method works as expected, returning the correct JSON record and storing the content as a String with this line: String secretString = model.getCertainSecret(title).getContent();

With that said...

Questions (partial answers fully appreciated too):

  1. secretString above now holds a confidential value (12345) which is obtained using a supposedly secure REST method. But couldn't a user simply reverse-engineer my source code and write System.out.println(secretString) and have that 12345 revealed? I don't understand how a simple string is protected after retrieving it from the server, despite not being explicitly shown. The code seems correct yet the value is easily obtainable. What am I missing?

  2. How do you put entire java methods on a server? A lot of code I need to protect isn't just strings but methods containing Tasks, Platform.runLater()->, and needs to interact with other desktop software. For example, one of my methods uses JACOB to identify when a certain area of a third-party software is clicked. I can't even fathom what a get/put would look like in that context.

My assumption was that a server-side DB would store all content from my put requests, but I don't understand how it stores and returns a method? Should I be reading about servlets or SaaS or something? I'm focused on desktop users.

Code:

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.Data;
import org.apache.log4j.BasicConfigurator;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import static spark.Spark.get;
import static spark.Spark.put;

public class ServerDemo
{
    private static final int HTTP_BAD_REQUEST = 400;

    @Data
    static class NewSecretPayload {
        private String title;
        private String content;

        public boolean isValid() {
            return title != null && !title.isEmpty();
        }
    }

    public static class Model {
        private int nextId = 1;
        private Map<String, Secret> secrets = new HashMap<>();
        @Data
        class Secret {
            private int id;
            private String title;
            private String content;
        }

        public int createSecret(String title, String content){
            int id = nextId++;
            Secret secret = new Secret();
            secret.setId(id);
            secret.setTitle(title);
            secret.setContent(content);
            secrets.put(title, secret);
            return id;
        }

        public Secret getCertainSecret(String titleToUse){
            if(null != secrets.get(titleToUse)){
                return secrets.get(titleToUse);
            }else{
                return null;
            }
        }
    }

    public static String dataToJson(Object data) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(SerializationFeature.INDENT_OUTPUT);
            StringWriter sw = new StringWriter();
            mapper.writeValue(sw, data);
            return sw.toString();
        } catch (IOException e) {
            throw new RuntimeException("IOException from a StringWriter?");
        }
    }

    public static void main(String[] args) {
        Model model = new Model();
        BasicConfigurator.configure();
        put("/secrets", (request, response) -> {
            try {
                ObjectMapper mapper = new ObjectMapper();
                NewSecretPayload creation = mapper.readValue(request.body(), NewSecretPayload.class);
                if (!creation.isValid()) {
                    response.status(HTTP_BAD_REQUEST);
                    return "";
                }
                int id = model.createSecret(creation.getTitle(), creation.getContent());
                response.status(200);
                response.type("application/json");
                return id;
            } catch (JsonParseException jpe) {
                response.status(HTTP_BAD_REQUEST);
                return "";
            }
        });

        get("/secrets/:title", (req, res) -> {
            String title = req.params(":title");
            if (model.getCertainSecret(title) != null) {
                res.status(200);
                res.type("application/json");
                String secretString = model.getCertainSecret(title).getContent();
                return dataToJson(model.getCertainSecret(title));
            }
            res.status(400);
            return new ResponseError("No user with title "+title+" was found", title);
        });
    }
}
Mathomatic
  • 899
  • 1
  • 13
  • 38
  • I'm confused by most of the assumptions in this question: What makes you believe any content inside a JSON response is hidden from a user? Or how do you send methods via JSON? JSON is a data format, I'm not sure how you are planning to embed Java methods into it. – UnholySheep Nov 04 '16 at 22:25
  • I'm not sure either, clearly :) To answer your question, I assumed that I would initially `put` all my sensitive code (methods, vars) onto the server and then distribute my app. Users would then have a "shell" of the software which requests certain pieces of code from the server via `get` methods, whenever required. I wrongly assumed JSON hid this... if JSON doesn't hide the value upon the request, how do you properly retrieve data from the server so it's never exposed? Entire methods need to be protected, and only called upon when required. Is this possible? Thank you. – Mathomatic Nov 04 '16 at 22:32
  • That is not how network communication works at all. Any data sent through can be read (it just may be a bit harder in some cases). If you don't want the user to have access to something then you can't send it. And your entire approach seems strange to me. Why would you want to send methods and variables? What advantage is that supposed to provide over having them in the binary program the user is executing? – UnholySheep Nov 04 '16 at 22:37
  • In another question I posted [here](http://stackoverflow.com/questions/40348787/javafx-put-sensitive-code-and-computations-on-server-side) there are 2 notable quotes from other SO answers.. "Move the most critical parts of the service out of the app, and into a web service, hidden behind a server side language like PHP. Move the algorithm and have it process the data on a remote server, and use the app to simply provide it with the data." and also "Set up a server that responds to requests from your app, "uses" the assets and then sends the result back to the app." – Mathomatic Nov 04 '16 at 23:09
  • These are my influences in my approach, how do I accomplish what they're proposing? I want to hide the code of certain methods/vars because they could be very useful to somebody who decompiled them. ProGuard isn't enough, so I want to move them server side. How do I do this so that their functionality can still be used as if they were integrated in the source code? I'm so lost – Mathomatic Nov 04 '16 at 23:14
  • The suggestions you quoted specifically state the the code is being executed server-side and only data is transfered back and forth (which is how RESTful architectures work). This means that your application calls a REST endpoint and sends data if necessary (e.g.: for a `POST` method) and receives an answer from the server (which may contain other data). However the data being sent is not hidden in any way. And you do not send the functions to be executed, they are defined on the server. The handler for the "address" of the REST endpoint determines which functions will get called. – UnholySheep Nov 04 '16 at 23:22
  • Therein lies my confusion: You say that functions are defined on the server, and are also executed server-side. How do I get them there? How do I execute them from the client side? Those are the 2 glaring questions I can't find answers for. I wrongly assumed I used `put` to upload them to server+execute. The additional question is: Some of my methods need to check if a user clicks within a third-party software, which means the COM interface using Jacob. How would I get that function to execute on the server, while still being able to listen for that click? Any tutorials, concepts or tip help – Mathomatic Nov 04 '16 at 23:27
  • I also don't understand where functions(methods) should be placed on a server in reference to the URL, is it a directory such as `www.mysite.com/secrets/method5/` which would perform a function if I upload a method in a .js file to that directory, or something? – Mathomatic Nov 04 '16 at 23:33
  • What do you mean *"How do I get them there?"*? The functions are written in your server-side code and stored on the server. Your client only calls the endpoint which is exposed to the network. The client should not have any way of directly accessing functions on the server (as that would be a huge security risk), that's why you define an interface. As for the click thing: Your desktop application calls an endpoint in response to the click event. – UnholySheep Nov 04 '16 at 23:34
  • Your last comment makes me believe you do not understand the concepts of RESTful APIs or Server-Side programming at all. You should probably take the time to read some tutorials about that and try to understand exactly how they are used. – UnholySheep Nov 04 '16 at 23:36
  • I certainly will, thanks for your time. I assumed that server-side code was in the form of a .java/.js file or something that is uploaded to the server and then referenced when needed from the client code. Are you able to suggest a tutorial to help me understand your statement: "functions are written in your server-side code and stored on the server"? I can find a lot of beginner tutorials explaining the basic HTTP methods but not discussing writing/storing server-side functions, or mentioning "endpoints" and exposing them to the network. I'll go with whatever you have (or don't). Thx. – Mathomatic Nov 04 '16 at 23:53
  • I once was blind but now I see, at least better. I fully understand each of your comments now that I took some more time to let them sink in. I see what you mean by endpoints now and how the handlers on the server side are what respond to the client's calls. Any sensitive functionality is performed on the server and if necessary, non-sensitive data is reported back. My demo code is server side code (duh)... and I now need to learn how to properly call this code from my client. [Helpful link](https://www.mkyong.com/webservices/jax-rs/restfull-java-client-with-java-net-url/) – Mathomatic Nov 05 '16 at 00:43

1 Answers1

0

Lets dig down to your first problem "Keeping string secret" :--

  • Restrict : The simplest way is not to provide the data to malicious user.
  • Masking : Mask the data you are providing to end user. You will have the original data mapped to masked data. You will provide masked data to end user. Here the end user can never get the original data as it is a one way process. When end user sends masked-data you can always retrieve the original data from it.
  • Encrypting : If the end user needs to see the data you can encrypt it and send it. You can make a sanity check of your code before decrypting the data. The sanity check can give you idea if the code is ever modified. If code fails the sanity check you can always exit the process.
Sidharth Dash
  • 333
  • 1
  • 4
  • 13