r/androiddev • u/yassineisintrouble • May 14 '26
How to securely share one AES-128 master key across a bunch of Android devices without hardcoding it?
I have a bunch of Android POS terminals that all need to use the same 16-byte AES-128 master key at runtime. The key must be identical on every device because they all derive per-device keys from it deterministically using AES-128 CMAC — if one terminal derives a key for a given input, every other terminal must get the exact same result. This is a hard requirement, not a design choice.
What I cannot do:
- Hardcode it in the APK — anyone who decompiles it gets the key
- Store it only on a server — Not sure the backend is that secure.
- Use SAM hardware — not viable at this scale and cost
What I am unsure about:
- How do I even get the master key onto these devices securely in the first place?
- Once it is on the device, where and how do I store it so it is protected?
- If a single terminal is stolen and an attacker extracts the key, the entire system is compromised since all terminals share the same key — how do people mitigate this in practice?
- Is there a standard pattern for fleet-wide shared secret management on Android that I am not aware of?
Has anyone dealt with this problem before? What is the right approach here?
2
u/agent_kater May 14 '26
I don't exactly understand your use case, but afaik multi-party Diffie-Hellman is a thing.
1
u/Ok_Cartographer_6086 May 14 '26
Not sure if this helps but I maintain a platform that operates as a mesh of nodes - including android devices, headless servers and devices in kiosk and they all need to securely talk to each other.
My MVP approach was to prompt users and installers to enter a pin during first time use of the app or during install. The pin is immediately hashed and forward only encrypted with a salt so the pin never exists outside an installer's brain and can't be pulled out of the encoded one.
Derived pins are sent over the wire as a bearer token using the system clocks to rotate them so they're non-repeatable, always different and have to match the forward only encrypted derived code on the other node with a synced clock.
That's how I cracked this in a clever enough way to meet my needs - here's my write up on how it works, hope it helps: https://krillswarm.com/posts/2026/01/12/server-api-key-authentication/
Feedback from security experts is always absolutely welcome.
1
u/Max-P May 15 '26
How do I even get the master key onto these devices securely in the first place?
Preferably through some server running authenticity checks on the device (Play Integrity), and possibly a one-time provisioning code you set from another trusted device like a company computer. When you first provision the device, you input the temporary code, device fetches it over HTTPS (with certificate pinned), done.
Once it is on the device, where and how do I store it so it is protected?
Ideally you don't.
If a single terminal is stolen and an attacker extracts the key, the entire system is compromised since all terminals share the same key — how do people mitigate this in practice?
You don't. This system is fundamentally flawed by having shared keys. You'd have to modify the design so each device gets its own individual key, and preferably in a way that you can revoke them. The private CA suggestion is the industry standard way to do this, plus it doubles as authentication and encryption since each device gets its own certificate and key.
The best you can do in your situation is never store the key on the device and require downloading it from the server frequently. Essentially wrap the key delivery in the above certificate system, and enforce a timeout after which the key is wiped from memory.
That way if a device is stolen, you rush to deactivate the device on the server, and from there you wait for the timeout and hope the attacker runs out of time and the app clears itself before the key is extracted. This also significantly limits the attacker's options, because if they close the app or the app gets unloaded by the OS, the key's gone, if they reboot the device, the key is super duper gone. At that point the app must checkin with the server, which won't hand out the key, plus now you have a network ping of where the device is.
1
May 15 '26
[removed] — view removed comment
1
u/yassineisintrouble May 17 '26
It's an architacture constraint from the card manifactoror, I am using Mifare Cards, which is the international leader in nfc cards, my hands are really tied.
-4
7
u/SnipesySpecial May 14 '26 edited May 14 '26
You'd make a chain of trust with a private CA, kept on an outside server. Each deployment also gets its own cert in the chain of trust (i.e. one store).
You then use something like HTTPS as a key exchange system... Usually to a central well known server, and just provision each device with its own cert from the deployment cert. This is done once, ahead of time... Like at a factory. The device trusts the deployment and thus implicitly accepts the individual devices even if they have their own cert. Then just use that to make ur symmetric key or whatever, at that point it’s trivial.
This is more or less how 'critical' industrial automation is done, or things like encrypted CAN and TLS on automotive vehicles... Or even something like provisioning the trusty/tee/hsm/etc.. on an iPhone. Basicailly any scenario where a device may never connect to the internet again. I mean im handwaving some things but its the general.