Best practice for storing and protecting private API keys in applications [closed]
Asked Answered
S

13

474

Most app developers will integrate some third party libraries into their apps. If it's to access a service, such as Dropbox or YouTube, or for logging crashes. The number of third party libraries and services is staggering. Most of those libraries and services are integrated by somehow authenticating with the service, most of the time, this happens through an API key. For security purposes, services usually generate a public and private, often also referred to as secret, key. Unfortunately, in order to connect to the services, this private key must be used to authenticate and hence, probably be part of the application. Needless to say, that this faces in immense security problem. Public and private API keys can be extracted from APKs in a matter of minutes and can easily be automated.

Assuming I have something similar to this, how can I protect the secret key:

public class DropboxService  {

    private final static String APP_KEY = "jk433g34hg3";
    private final static String APP_SECRET = "987dwdqwdqw90";
    private final static AccessType ACCESS_TYPE = AccessType.DROPBOX;

    // SOME MORE CODE HERE

}

What is in your opinion the best and most secure way to store the private key? Obfuscation, encryption, what do you think?

Stasiastasis answered 28/1, 2013 at 20:50 Comment(3)
rammic.github.io/2015/07/28/hiding-secrets-in-android-appsLilas
i had store in image/png and get key through png as BufferReaderArminius
I think that this is a valid concern and posted a similar issue on the Firebase Android SDK github page: github.com/firebase/firebase-android-sdk/issues/1583. Let's see if this gets handled.Girondist
P
418
  1. As it is, your compiled application contains the key strings, but also the constant names APP_KEY and APP_SECRET. Extracting keys from such self-documenting code is trivial, for instance with the standard Android tool dx.

  2. You can apply ProGuard. It will leave the key strings untouched, but it will remove the constant names. It will also rename classes and methods with short, meaningless names, where ever possible. Extracting the keys then takes some more time, for figuring out which string serves which purpose.

    Note that setting up ProGuard shouldn't be as difficult as you fear. To begin with, you only need to enable ProGuard, as documented in project.properties. If there are any problems with third-party libraries, you may need to suppress some warnings and/or prevent them from being obfuscated, in proguard-project.txt. For instance:

    -dontwarn com.dropbox.**
    -keep class com.dropbox.** { *; }
    

    This is a brute-force approach; you can refine such configuration once the processed application works.

  3. You can obfuscate the strings manually in your code, for instance with a Base64 encoding or preferably with something more complicated; maybe even native code. A hacker will then have to statically reverse-engineer your encoding or dynamically intercept the decoding in the proper place.

  4. You can apply a commercial obfuscator, like ProGuard's specialized sibling DexGuard. It can additionally encrypt/obfuscate the strings and classes for you. Extracting the keys then takes even more time and expertise.

  5. You might be able to run parts of your application on your own server. If you can keep the keys there, they are safe.

In the end, it's an economic trade-off that you have to make: how important are the keys, how much time or software can you afford, how sophisticated are the hackers who are interested in the keys, how much time will they want to spend, how much worth is a delay before the keys are hacked, on what scale will any successful hackers distribute the keys, etc. Small pieces of information like keys are more difficult to protect than entire applications. Intrinsically, nothing on the client-side is unbreakable, but you can certainly raise the bar.

(I am the developer of ProGuard and DexGuard)

Potage answered 28/1, 2013 at 22:1 Comment(16)
Is this a local server being talked about in the fifth point? Wouldn't this need a computer that requires to stay on always? Sorry, I'm a newbie. Can I use something like Parse?Gobo
@EricLafortune does it not make a difference if the private key string is stored in the Java class vs in the String resource XML?Goodrich
@EricLafortune Is it now possible to use the Android Keystore system to securely store the keys? ( developer.android.com/training/articles/keystore.html )Coonhound
@DavidThomas: Did you tried using keystore. I want to obfuscate a API key written in Java class. Please replySyracuse
@SagarTrehan no, I haven't tried the keystore approach yet. There is a popular utility called "dexguard" that may be of interest to you there.Coonhound
Is Android KeyStore useful for this? (developer.android.com/training/articles/…)Ecchymosis
I don't understand #5. Doesn't it have the same exact problems as the original problem?Ain
@pete: #5 means that a server you own acts as a go-between in the authentication. The API keys will be stored only on your server and not be included in any code that leaves your control.Spray
What about storing the keys in a database (e.g. embedded sqlite) using a strong key derivation algorithm (e.g. bcrypt, argon2, ...)? Wouldn't it act the same as keeping them everywhere else (even on server) as the only way to get them would be to run the code and intercept the decoding in the proper place?Foggy
@Bart van ignen Schenau, I have the same question as Pete. What's to prevent someone from decompiling your app and seeing how function() works. They could then copy the algorithm and communicate with your server to execute bad things.Incorrigible
@sudocoder: Naturally, your server would validate that the requests come from a authenticated user.Spray
@BartvanIngenSchenau how would i send requests to a server to validate that I am indeed authenticated? I can think of a solution... I'd send a private key credential... but isn't that the original problem we're trying to solve?Incorrigible
@Incorrigible You ask the user for login credentials to authenticate. If your app does not require user/client authentication, then perhaps all you need is employ rate-limiting and DoS defenses at the backend server.Whaley
We provide a free and open-source Dexguard alternative to deeply hide secret keys in Android. This is a gradle plugin that uses the NDK and XOR operator to prevent from reverse-engineering : github.com/klaxit/hidden-secrets-gradle-pluginWashwoman
This answer miss the man-in-the-middle security issues.Caesar
#5 is the only completely correct answer here. Reverse engineering is trivial. Yeah, you can encrypt and hide something, but you then have to go through huge lengths to hide your networking layer, because the keys still pass through. It's trivial to RE an app and drop a log statement right before a call or MitM the request. If you want to protect an API key, keeping it server side and using your auth credentials to cross-check permissions and proxy the call from there is the only way.Phyle
S
99

Few ideas, in my opinion only first one gives some guarantee:

  1. Keep your secrets on some server on internet, and when needed just grab them and use. If user is about to use dropbox then nothing stops you from making request to your site and get your secret key.

  2. Put your secrets in jni code, add some variable code to make your libraries bigger and more difficult to decompile. You might also split key string in few parts and keep them in various places.

  3. use obfuscator, also put in code hashed secret and later on unhash it when needed to use.

  4. Put your secret key as last pixels of one of your image in assets. Then when needed read it in your code. Obfuscating your code should help hide code that will read it.

If you want to have a quick look at how easy it is to read you apk code then grab APKAnalyser:

http://developer.sonymobile.com/knowledge-base/tool-guides/analyse-your-apks-with-apkanalyser/

Schopenhauerism answered 28/1, 2013 at 21:7 Comment(15)
if user can decompile app though they could likely determine request that was made to your own server and simply execute that to get secret. No silver bullet here but take a few steps and I bet you'll be fine! If your app is super popular though maybe not.. Great ideas!Telemann
yeah, number 1 gives no guarantee.Schopenhauerism
I really like the idea of hiding keys inside images. +1Wicker
I prefer number 2, take a look at: github.com/sanandrea/CSecretKey waiting for some comments/advicesUndergraduate
@MarcinJędrzejewski Would you like to explain more(with sample or snipped code preferably) about forth solution? Thank you.Coen
@Mr.Hyde this is called steganography, its way too complex to give a sample code here, you can find examples on google. I have found one here: dreamincode.net/forums/topic/27950-steganography. The idea is great but since apk code can be decompiled it spoils its beauty.Schopenhauerism
@MarcinJędrzejewski It's interesting, there are too many algorithm for steganography. Do you know any tools that can use on both windows os side, and android? I want to encode message in PC, and just use deciding method inside my android application.Coen
yeah i already had stored in image file and get key through image as BufferReader, not secure but good to goArminius
How does #1 help? The attacker can just query the server for the secret key before querying your main service, so it's just as easy as before to impersonate your app isn't it?Ain
How does #3 work? How do you "unhash"Ain
Correct me if i'm wrong, #1 works because you log in and you're granted a session token. Then you make every call through your server with this session token - the server fetches and returns information for you. That means if I want to call dropbox's api i'd have to go through my server first with my granted session token.Incorrigible
@Incorrigible not really, its explained in comments - this idea was about using request to your server to get api key (or any other secret) over https connection. This way you dont keep secret in apk, but as explained in comment, hacker might find out the http request and try to call it. This is where security over obsurity starts,:-) you could pack your secret in the image using some form of steganografy and decode it in native c++ code. Still clever hacker will simply print this key before the dropbox request is formed - after all that obsurity....Schopenhauerism
@Incorrigible your idea about using own server as a proxy to dropbox seems very nice, api keys will be protected this way - but it might complicate use of dropbox apis. In recent times I found that fight with hackers is difficult, what worked for me was to analyze what hackers have changed in apk to break security and do fixes around those places to protect them. It takes few hours, maybe a day. Release new updated apk quite often and make sure your content will work only with newest (or two last versions..) versions so that pirates will not be able to use old cracked ones.Schopenhauerism
No4 is intersting but can't say it's secure.Malmsey
I genrate QR code for the multiple keys and store it as one single image, when i need to use the key i call the method which can read the QR code. yes every method will Obfuscate.Malmsey
A
62

Another approach is to not have the secret on the device in the first place! See Mobile API Security Techniques (especially part 3).

Using the time honored tradition of indirection, share the secret between your API endpoint and an app authentication service.

When your client wants to make an API call, it asks the app auth service to authenticate it (using strong remote attestation techniques), and it receives a time limited (usually JWT) token signed by the secret.

The token is sent with each API call where the endpoint can verify its signature before acting on the request.

The actual secret is never present on the device; in fact, the app never has any idea if it is valid or not, it juts requests authentication and passes on the resulting token. As a nice benefit from indirection, if you ever want to change the secret, you can do so without requiring users to update their installed apps.

So if you want to protect your secret, not having it in your app in the first place is a pretty good way to go.

Acetate answered 2/2, 2018 at 21:12 Comment(3)
The problem persists when you want to access the authentication service. It will give you a client id and client secret. Where should we save them?Thrombo
doesn't solve private apis where you need to authenticate to your api first in order to use it. where do you get the credentials for all app users?Uremia
@Thrombo client id is somewhat obfuscated in a way that only api endpoint knows on how to extract data from obfuscated data like if only some of the characters of client id(where client id is actual client id + some more data to create obfuscated string )only means the actual data but if hacker tries to change or make changes to client id, he doesn't know which data actually represents client id because that is actually known only to api end point on how client id has been obfuscated and how to extract useful data from client id which actually represents client id.... hope u get my pointThreap
J
35

Old unsecured way:

Follow 3 simple steps to secure the API/Secret key (Old answer)

We can use Gradle to secure the API key or Secret key.

1. gradle.properties (Project properties): Create variable with key.

GoogleAPIKey = "Your API/Secret Key"

2. build.gradle (Module: app) : Set variable in build.gradle to access it in activity or fragment. Add below code to buildTypes {}.

buildTypes.each {
    it.buildConfigField 'String', 'GoogleSecAPIKEY', GoolgeAPIKey
}

3. Access it in Activity/Fragment by app's BuildConfig:

BuildConfig.GoogleSecAPIKEY

Update:

The above solution is helpful in the open-source project to commit over Git. (Thanks to David Rawson and riyaz-ali for your comment).

As per Matthew and Pablo Cegarra's comments, the above way is not secure and Decompiler will allow someone to view the BuildConfig with our secret keys.

Solution:

We can use NDK to Secure API Keys. We can store keys in the native C/C++ class and access them in our Java classes.

Please follow this blog to secure API keys using NDK.

A follow-up on how to store tokens securely in Android

Josephina answered 29/11, 2017 at 12:55 Comment(12)
storing a key in gradle file is secure?Afford
@Afford gradle.properties shouldn't be checked in to Git so this is a way of keeping the secret out of committed source code, at leastUterine
This doesn't prevent the API key from being bundled into the resulting apk (it will be add to the generated BuildConfig file), although this is definitely a good idea to manage different API keys (for e.g. in an open source project)Sizzle
Using a Java Decompiler will allow someone to view the BuildConfig file and "GoogleSecAPIKEY"Fuchsin
Your BuildConfig.java file will have the key in plain text form. This is no better than what the OP is already doing.Biretta
The very large, bold text at the top of your answer should probably not say "secure" if the solution is quite obviously insecure, as pointed out. I know you have an "update" section in there, but many people proooobably don't read that.Claudelle
About the NDK solution we have created a free gradle plugin that obfuscate and store your key in C++ files, accessible from your Java code. All the details here : github.com/klaxit/hidden-secrets-gradle-pluginWashwoman
I don't think storing a secret in NDK is secure either. Here's how I think it is vulnerable - When an NDK is used, a .so file is generated which is the compiled version of the c/c++ code. So, someone can extract this .so file from your app and call it the way you call it to get the secret. So, it is quite easy for someone who knows how to work with .so files. Please correct me here, I'm trying to find a good way to solve this problem myself.Scandinavia
@ShubhamAgarwal Above mentioned medium blog is from the Google Developers Experts medium.com/google-developer-experts/…Josephina
I checked the blog and I got my answer. There is a comment mentioning that it can be extracted by putting a breakpoint and checking it. That was my concern.Scandinavia
No, NDK is not a secure way to secure APIs or Any secrete Keys. I suggest using Cryptography to secure.Honeybunch
For more clarification in kotlin android: medium.com/@khadijahameed415/…Heavyduty
G
22

Adding to @Manohar Reddy solution, firebase Database or firebase RemoteConfig (with Null default value) can be used:

  1. Cipher your keys
  2. Store it in firebase database
  3. Get it during App startup or whenever required
  4. decipher keys and use it

What is different in this solution?

  • no credintials for firebase
  • firebase access is protected so only app with signed certificate have privilege to make API calls
  • ciphering/deciphering to prevent middle man interception. However calls already https to firebase
Geezer answered 12/9, 2018 at 22:22 Comment(3)
with all do respect with this solution we are still the first square. Instead of using credentials , you suggest to use a certificate. Whoever is capable of stealing your credentials is capable of stealing your signed certificate.Thrombo
One advantage though, with the suggested solution, we are adding one more complication in front of the hacker.Thrombo
We never keep our private certs in source code, so chance no of stealing, right?Lamppost
B
19

One possible solution is to encode the data in your app and use decoding at runtime (when you want to use that data). I also recommend to use progaurd to make it hard to read and understand the decompiled source code of your app . for example I put a encoded key in the app and then used a decode method in my app to decode my secret keys at runtime:

// "the real string is: "mypassword" "; 
//encoded 2 times with an algorithm or you can encode with other algorithms too
public String getClientSecret() {
    return Utils.decode(Utils
            .decode("Ylhsd1lYTnpkMjl5WkE9PQ=="));
}

Decompiled source code of a proguarded app is this:

 public String c()
 {
    return com.myrpoject.mypackage.g.h.a(com.myrpoject.mypackage.g.h.a("Ylhsd1lYTnpkMjl5WkE9PQ=="));
  }

At least it's complicated enough for me. this is the way I do when I have no choice but store a value in my application. Of course we all know It's not the best way but it works for me.

/**
 * @param input
 * @return decoded string
 */
public static String decode(String input) {
    // Receiving side
    String text = "";
    try {
        byte[] data = Decoder.decode(input);
        text = new String(data, "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return "Error";
}

Decompiled version:

 public static String a(String paramString)
  {
    try
    {
      str = new String(a.a(paramString), "UTF-8");
      return str;
    }
    catch (UnsupportedEncodingException localUnsupportedEncodingException)
    {
      while (true)
      {
        localUnsupportedEncodingException.printStackTrace();
        String str = "Error";
      }
    }
  }

and you can find so many encryptor classes with a little search in google.

Blouson answered 18/6, 2016 at 10:11 Comment(1)
I think this is getting close to the best solution, but combine this with statically linked NDK code that hashes the "running app name" and uses this resulting hash to decrypt the secret.Froze
G
16

The App-Secret key should be kept private - but when releasing the app they can be reversed by some guys.

for those guys it will not hide, lock the either the ProGuard the code. It is a refactor and some payed obfuscators are inserting a few bitwise operators to get back the jk433g34hg3 String. You can make 5 -15 min longer the hacking if you work 3 days :)

Best way is to keep it as it is, imho.

Even if you store at server side( your PC ) the key can be hacked and printed out. Maybe this takes the longest? Anyhow it is a matter of few minutes or a few hours in best case.

A normal user will not decompile your code.

Gingersnap answered 28/1, 2013 at 20:54 Comment(5)
Well - not the answer I hoped to get =) ... I thought you can achive great security :(Stasiastasis
sorry it is not as you wanted a brillinant, ultra safe solution, but for those who can use the compiler, decompiler there is no safe java code: even the native code can be viewed with hexa viewer and decrtyped. At least worth a try...Gingersnap
Proguard wont obfuscate the actual key though..? Best thing to do is some simple encript/decript routine, that obfuscate will hide.Easter
it is "visible" the decryption routine, is easy to make the reverse and you have the original stringGingersnap
Even if you could protect it on the device, you definitely cant protect user from looking at his own network logs, where secret may be passed .Provisory
V
14

This example has a number of different aspects to it. I will mention a couple of points that I don't think have been explicitly covered elsewhere.

Protecting the secret in transit

The first thing to note is that accessing the dropbox API using their app authentication mechanism requires you to transmit your key and secret. The connection is HTTPS which means that you can't intercept the traffic without knowing the TLS certificate. This is to prevent a person intercepting and reading the packets on their journey from the mobile device to the server. For normal users it is a really good way of ensuring the privacy of their traffic.

What it is not good at, is preventing a malicious person downloading the app and inspecting the traffic. It is really easy to use a man-in-the-middle proxy for all traffic into and out of a mobile device. It would require no disassembly or reverse engineering of code to extract the app key and secret in this case due to the nature of the Dropbox API.

You could do pinning which checks that the TLS certificate you receive from the server is the one you expect. This adds a check to the client and makes it more difficult to intercept the traffic. This would make it harder to inspect the traffic in flight, but the pinning check happens in the client, so it would likely still be possible to disable the pinning test. It does make it harder though.

Protecting the secret at rest

As a first step, using something like proguard will help to make it less obvious where any secrets are held. You could also use the NDK to store the key and secret and send requests directly, which would greatly reduce the number of people with the appropriate skills to extract the information. Further obfuscation can be achieved by not storing the values directly in memory for any length of time, you can encrypt them and decrypt them just before use as suggested by another answer.

More advanced options

If you are now paranoid about putting the secret anywhere in your app, and you have time and money to invest in more comprehensive solutions, then you might consider storing the credentials on your servers (presuming you have any). This would increase the latency of any calls to the API, as it will have to communicate via your server, and might increase the costs of running your service due to increased data throughput.

You then have to decide how best to communicate with your servers to ensure they are protected. This is important to prevent all of the same problems coming up again with your internal API. The best rule of thumb I can give is to not transmit any secret directly because of the man-in-the-middle threat. Instead you can sign the traffic using your secret and verify the integrity of any requests that come to your server. One standard way of doing this is to compute an HMAC of the message keyed on a secret. I work at a company that has a security product that also operates in this field which is why this sort of stuff interests me. In fact, here is a blog article from one of my colleagues that goes over most of this.

How much should I do?

With any security advice like this you need to make a cost/benefit decision about how hard you want to make it for someone to break in. If you are a bank protecting millions of customers your budget is totally different to someone supporting an app in their spare time. It is virtually impossible to prevent someone from breaking your security, but in practice few people need all of the bells and whistles and with some basic precautions you can get a long way.

Vermis answered 17/1, 2017 at 13:32 Comment(3)
You just copy and pasted this from here: hackernoon.com/mobile-api-security-techniques-682a5da4fe10 without acknowledging the source.Cycloparaffin
@Cycloparaffin I agree that he should have quoted the article you linked, but he may have forgot it because both work in same place...Aldwon
Also Skip's article and the blog post they are based on came out a week after my answer.Vermis
J
9

Whatever you do to secure your secret keys is not going to be a real solution. If developer can decompile the application there is no way to secure the key, hiding the key is just security by obscurity and so is code obfuscation. Problem with securing a secret key is that in order to secure it you have to use another key and that key needs to also be secured. Think of a key hidden in a box that is locked with a key. You place a box inside a room and lock the room. You are left with another key to secure. And that key is still going to be hardcoded inside your application.

So unless the user enters a PIN or a phrase there is no way to hide the key. But to do that you would have to have a scheme for managing PINs happening out of band, which means through a different channel. Certainly not practical for securing keys for services like Google APIs.

Jadeite answered 15/12, 2016 at 16:27 Comment(0)
S
6

The most secure solution is to keep your keys on a server and route all requests needing that key through your server. That way the key never leaves your server, so as long as your server is secure then so is your key. Of course there is a performance cost with this solution.

Saxhorn answered 24/9, 2016 at 15:41 Comment(10)
The problem is - to reach that server which contains all the secrects i should use another Secret Key - I wonder where i will keep that ? ;) What i am trying to say is - This is also not the best solution (don't think there is an ideal solution here)Jaundiced
That's not true, your server is completely under your control. What it requires is entirely up to you.Saxhorn
Can you explain here how client can encrypt the data he wants to send to the server, while the keys are in the server side ? and if your answer will be - The server sends keys to the client - So that must be secured as well! so again no magic solution! can't you see?!Jaundiced
@Jaundiced lolz, I came here and immediately after seeing the "keep your keys in your private server" I just think the same. You also need to secure the key to your private server or the hacker can just go to your server and grab the key. At the end you have a vicious cycle without solution. It's funny cause I came here to find a simple solution of hiding the API key to MY server. And they are suggesting I should make another server for that and then run into the some problems over and over againGeiger
@Geiger your If you want to learn about keeping a server secure this is good place to start: cyberciti.biz/tips/linux-security.html Regardless, SSH with key authentication and VPN/firewall are the basic ways to access a server remotely without giving out access to the world. The SSH key sits on your personal computer.Saxhorn
@BernardIgiri, Aren't you missing the whole point of it all? The whole point is to be able to access the server from the mobile application you're building without making it vulnerable because everyone who has the app can retrieve the access keys and tokens by dissambling the app. What have ssh with key authentication and keys been stored on your PC to do with that?Geiger
@Geiger so the issue you are trying to resolve is preventing others from using your server? I only know of one solution, authentication. Users will have to create an account and login to access the server. If you don't want people to have to put in their information, you could have the app automate it. The app could generate a random login token on the phone, send the request to the server with the phone #, and the server can respond with a random pin to the phone. Upon verification of the pin the account is created, and the token is all that is needed from there on.Saxhorn
@BernardIgiri and then again we are back to square 1. Let's assume, the phone creates a random login and the server accepts that and sends a pin(This is the so called private server we are talking). Then the person who disassembles your app sees that all it takes to access your private server is just some random login that he can create himself. Tell me what stops him from creating one and accessing your server? In fact what is the difference between your solution and actually storing a login or api key to the main server (whose credentials we wanted to store in our private server)Geiger
@ken The random number is authenticated against the phone number and physical access to its text messages. If someone cheats you, you have their information. If that's not good enough force them to create a full user account and password. If that's not good enough get a credit card too. If that's not good enough have them call in. If that's not good enough meet them face to face. How secure/inconvenient do you want to be?Saxhorn
i believe @Bernardlgiri answer is quite good, as the server will make the api call to only a specific api endpoints and will only allow some calls based on the authentication and also firebase security rules. The response from the API call is what would be sent back and not the API key. Kindly enlighten me if this method exposes exploits.Monterrey
B
5

The only true way to keep these private is to keep them on your server, and have the app send whatever it is to the server, and the server interacts with Dropbox. That way you NEVER distribute your private key in any format.

Brine answered 7/5, 2016 at 18:55 Comment(6)
But how do you prevent the rest of the world from calling the server?Burse
If by "the server" you mean your webserver where the credentials are - you can use any method you want. simple authentication with username / password, oauth, active directory, etc. etc. Really depends on your application.Brine
Maybe I'm missing something, but doesn't this still require storing credentials within the app?Burse
No, the dropbox credentials are stored on your application server, the app talks to your application server, which handles any dropbox requests.Brine
Right, but you said the app would authenticate with the server first. Doesn't this mean storing another set of credentials in the app? I understand the server would handle the actual dropbox calls.Burse
Well, it could mean that, but it a completely separate authorization. But you don't have to. The usecase I am talking about is that your app user would have a login to your app, say using facebook or twitter. You don't store their credentials in your app, you don't even know them. That authorization process allows them access to your api server, which has the credentials to dropbox, but no app or user has access to them directly.Brine
H
5

Keep the secret in firebase database and get from it when app starts , It is far better than calling a web service .

Hirokohiroshi answered 27/3, 2018 at 7:56 Comment(11)
but what about credentials to firebase?Monocyte
Unfortunately, Firebase database doesn't work in China.Absenteeism
doesn't make sense, attackers can see you firebase details from decompiled code and get any data from your datababseOssian
I think this is the best solution as firebase Apps uses SHA1 to allow access to server. Decompiling the code will not help to make call to firebase because hacker new app should use exact app stamp to access firebase. Also, stored key should be ciphered before storing in firebase DB and deciphered once received to avoid middle man interception.Geezer
When you get the secret from the firebase database through the network, how does that more secure than getting the same secret from another web service through a secure (https) channel? Can you explain?Posner
@CsabaToth see comment of Ayman Al-Absi . Also I am not saying Firebase Database is 100% attack proof but it is better than calling web service for key .Hirokohiroshi
good suggestion, but for government sector apps, its not prefered option.Cella
but in this way (from Firebase database) , How can I use the key in Manifest ?Nightclub
@NoorHossain what key are you talking about ?Hirokohiroshi
I'll +1 this because, keeping keys on different server (from API server) makes total sense.Vamp
Firebase database has significant downtime.Fuqua
B
4

Ages old post, but still good enough. I think hiding it in an .so library would be great, using NDK and C++ of course. .so files can be viewed in a hex editor, but good luck decompiling that :P

Bename answered 30/3, 2016 at 15:51 Comment(8)
Users can easily make function calls to the shared library and get whatever is hiding there. No need to decopile it.Folks
According to androidauthority.com/… there is no safe way to do it in android at the moment.Folks
@AhmedAwad Don't understand why this is having 3 upvote. any one could easily decompile the app and see how the ndk entry point are being called :/Hibiscus
This answer is almost one of the best options, but the author should mention that it is very important that you should include a call (inside your NDK library) to see if the checksum matches your APK as otherwise someone can call your NDK library outside of your appGargan
@Sniper that would be great, except it has a big problem. How do you know what file is "calling" the native method? If you hard-code the name of the apk to check, great, but what if I make my "hack" apk the same folder as the "good" apk? It will check that the "good" apk has good checksum, and it will allow me to execute that native method. Unless there's a way to know the caller file from JNI/C++ side, then it's pointless as the other options.Fioritura
Add hooks back from C++ side to use JNI to get the app's package name, hash it, and use that as a decryption key to decrypt the secret on the C++ side using nacl or libsodium.Froze
I was able to learn decompiling those NDK binaries in less than an hour by just searching in YouTube. Look for Binary Exploitation playlist by LiveOverflow. Just the videos 4, 5, 6 and 7 each 10 minutes long are enough and you only use free Foss tools. Real extraction only takes about 20 minutes.Histrionic
No need to decompile!! - Just import the lib and use it. - But The easier way is decompiling the apk, adding some lines to smali code and building it. Boom!!Fullfledged

© 2022 - 2024 — McMap. All rights reserved.