1

I am learning android and trying to make MY Application secure as much as possible. I have bought one android app which have below class

public class API {

    @SerializedName("sign")
    private String sign;
    @SerializedName("salt")
    private String salt;
    @SerializedName("package_name")
    private String package_name;

    public API(Activity activity) {
        String apiKey = "secretkey";
        salt = "" + getRandomSalt();
        sign = md5(apiKey + salt);
        package_name = activity.getApplication().getPackageName();
    }

    public API(Context context) {
        String apiKey = "secretkey";
        salt = "" + getRandomSalt();
        sign = md5(apiKey + salt);
        package_name = context.getApplicationContext().getPackageName();
    }

    private int getRandomSalt() {
        Random random = new Random();
        return random.nextInt(900);
    }

    private String md5(String input) {
        try {
            // Create MD5 Hash
            MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
            digest.update(input.getBytes());
            byte messageDigest[] = digest.digest();

            // Create Hex String
            StringBuilder hexString = new StringBuilder();
            for (int i = 0; i < messageDigest.length; i++)
                hexString.append(String.format("%02x", messageDigest[i]));
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String toBase64(String input) {
        byte[] encodeValue = Base64.encode(input.getBytes(), Base64.DEFAULT);
        return new String(encodeValue);
    }

}

And its using like below

JsonObject jsObj = (JsonObject) new Gson().toJsonTree(new API(Login.this));
        jsObj.addProperty("email", sendEmail);
        jsObj.addProperty("password", sendPassword);
        assert device != null;
        jsObj.addProperty("player_id", device.getUserId());
        jsObj.addProperty("method_name", "user_login");
        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
        Call<LoginRP> call = apiService.getLogin(API.toBase64(jsObj.toString()));

I think its securing data with encryption with API class

I am trying to use above method in my application but I am using RequestParams so I am not getting idea how I can use above in my case

RequestParams requestParam=new RequestParams();
        requestParam.put("mobile",mobile_number);
        requestParam.put("password","password");
AsyncHttpClient client = new AsyncHttpClient();
        client.get(BASE_URL+"login.php?",requestParams, new AsyncHttpResponseHandler() {

Let me know if anyone here can help me for solve my issue.

Thanks a lot!

Nidhi
  • 95
  • 9
  • Can you change from `GET` to `POST`? – aksappy Aug 16 '21 at 18:33
  • @aksappy that has no real effect on security. POST params are transimitted in plain text over http, and encrypted via https. The only reason to popssibly be concerned about GET vs POST is if your server automatically logs the full GET url. – Gabe Sechan Aug 16 '21 at 18:57

1 Answers1

0

As far as securing data, as long as you are using SSL/TLS, (even with GET), your data is encrypted during transfer.

That being said, the code above has MD5 and Base64 methods to convert the info to a hash. Using those functions, you can have a secret key shared between your app and the server, and use that key to encrypt/decrypt the hash values.

To make the md5 function more secure, you can create a know "salt" value rather than a random one, then update the function like this:

 public static String md5(String salt, String plainText)
        throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("MD5");

    if (salt != null) {
        md.update(salt.getBytes());
    }
    md.update(plainText.getBytes());

    byte byteData[] = md.digest();

    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < byteData.length; i++) {
        sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16)
                .substring(1));
    }
    return sb.toString();
}

And update the call like this:

requestParam.put("password", md5(md5(SALT_VALUE), md5(password));

Also, as a side-note, with GSON, you do not have to construct your own JSON objects, you can use the actual object reference and call .toJson()

RestingRobot
  • 2,938
  • 1
  • 23
  • 36
  • His use of MD5 provides no additional security. The data is already encrypted via HTTPS. Putting another layer of encryption on top of it doesn't make it more secure, and actually can make it less. Also, they key he makes the md5 hash from is on the client as part of the app, so trivially decompiled. Just rely on HTTPS to do the encryption and you're fine. – Gabe Sechan Aug 16 '21 at 19:01
  • Using an MD5 with salt would add additional security over HTTP and local logging intrusion. The key can be stored in build settings, so not trivially decompiled at all, or the key could passed via server handshake. I agree that md5 is not at all ideal, I was just working with the code provided. I disagree with both of your points, and would be happy explain why in further detail. – RestingRobot Aug 16 '21 at 19:25
  • The key can't be stored anywhere but in the client, because the client needs to know the key. Build settings hides things at compile time from your coworkers, not from the apk user once built. So yes, it will trivially be decompiled. And if you're using HTTP and not HTTPS, you already aren't caring about security. These days you shouldn't even have a plain HTTP server unless it just redirects to HTTPS. – Gabe Sechan Aug 17 '21 at 14:09
  • The key can absolutely be obtained at runtime? Why couldn't I just pass in a value sent to me from the server as salt? Gradle build settings do hide things from the apk when it is built. It is created as a computed resource, just like any resource. The things you are saying are provably false. – RestingRobot Aug 18 '21 at 16:04
  • Gradle resources do not hide things in the APK. THey're trivially decompilable. And they have to be- because they need to exist in the client for the client to use it. It may put a speed bump or two in there, but you can get the values with almost 0 effort. You apparently have no knowledge of reverse engineering. As for passing a value from the server as a salt- sure you could. But you're needlessly overcomplicating things, when the datapath is already encrypted. You'd also need a handshake to determine what the salt is, and the server would need to store it – Gabe Sechan Aug 19 '21 at 04:18
  • It would need to store it for every connection independently, as you wouldn't just reuse the same salt (if you are, then you're missing the point of a salt and providing minimal value with it, as it would be trivial to get the salt value from the server). So in order to do something that adds no additional security you're greatly increasing the complexity of your code and the number of network calls made. This is pointless. Just use HTTPS. – Gabe Sechan Aug 19 '21 at 04:21
  • The process I described is essentially the same process that a TLS handshake uses under the hood. So is it overkill, yes absolutely, but that was the question that was asked. It does make sense to do things like this, (albeit not with MD5), for various reasons however, (including the inability to use HTTPS for whatever reason). Your comment, "just use HTTPS" is asinine as its not always possible. – RestingRobot Aug 19 '21 at 18:29
  • Furthermore, using Gradle properties is not "trivially decompilable" as it generates a resource just like any other. How do you think any app stores API keys or any other type of sensitive info, (if not being served)? You end up with a resource property that can be obfuscated with Pro-Guard. Again, this is isn't completely un-decompilable, but to call it trivial is completely wrong. – RestingRobot Aug 19 '21 at 18:32
  • LOL the only one showing ignorance is you, [proguard does work on resource strings](https://stackoverflow.com/questions/14570989/best-practice-for-storing-and-protecting-private-api-keys-in-applications/14572051#14572051) Using HTTPS is always possible - False, I currently work on 2 such projects where it is not possible as communication is done via reliable UDP. – RestingRobot Aug 19 '21 at 20:01
  • You're the one here speaking in absolutes. As far as missing the context, read the first line of my answer. Please show me anywhere in the original question that lists HTTP as a requirement for an answer. – RestingRobot Aug 19 '21 at 20:06