I've got some sensitive data (api secret key) to store in the app on the client-side, I know this is a bad practice to store this kind of information but there are not feasible alternatives for now, I'm already tampering the problems that could arise if such key is leaked, but I wish to know if encoding such key in the build during compile time is secure or not, in case of decompiling the code, even if obfuscated, is it more difficult to retrive a compile-time variable?
Here an example of how I would use it
flutter build apk --dart-define=APP_VERSION=0.1.2 --dart-define=SECRET_KEY=123456
CodePudding user response:
This is precisely as insecure as any other approach.
Create project that uses the define
(If the define isn't used, it'll be stripped out, but obviously you want to use it.)
void main() {
const String key = String.fromEnvironment('SECRET_KEY');
print(key);
runApp(const MyApp());
}
Build
I'm using "SEKRET" here rather than "123456" because there are a lot of "123456" strings in a normal APK and it could give a false positive.
flutter build apk --dart-define=APP_VERSION=0.1.2 --dart-define=SECRET_KEY=SEKRET
Open the APK
cd build/app/outputs/flutter-apk/
mkdir app
cd app
unzip ../app-release.apk
Look for secret strings
strings lib/x86_64/libapp.so | grep SEKRET
> SEKRET
This is no different than just hardcoding the string into the app. There is no benefit to "hiding" it in a define, and there's no way to really secure this. The best you can do is obfuscate and hope the attacker isn't highly motivated. Or invest in ongoing obfuscation and hardening improvements every time they crack your system. (This is very difficult and expensive, and there is, by its nature, no universal or permenant solution.)
You cannot hide an API key in a binary. You cannot hide an API key that an app uses in memory. You cannot reliably keep secrets from someone who controls the hardware the app runs on and is motivated to find those secrets.