Kin Android development tutorial — part 4— Secure communication between backend and app for earning Kin
This is part 4 of the Kin Android development tutorial. In this post, I will explain how to set up secure communication between your Android app and a backend for earning Kin. The keyword secure is key here, it is very simple to create earn requests, but it would be horrible to find out a day later your wallet has been emptied. If you expose your earns insecurely it’s not even a “hack”, it’s like leaving the house with your front door open.
This post is about how you app interacts with other components like your backend and the Kin blockchain. This is a very important part of app development, and requires a bit of logical thinking instead of coding. Let’s go over the ways to set up earns from worst to best.
The worst way to set up earns
The absolute worst way to handle earns is the following:
In this example, your app communicates directly with the Kin blockchain, without any backend logic of your own. It is also the easiest, because you don’t have to build any backend logic. Even if you just want to build a minimum viable product (MVP) and want something shipped as soon as possible, don’t cut corners on secure communication. The flaw in this architecture is as follows:
The app does a request to send 100 Kin to address X to the Kin blockchain (where X is the user’s address). Of course you cannot directly issue a request to a blockchain. You do a request to a service that accepts payment requests, which in our case will be the Kin Python bootstrap server. The request will look something like this:
This means that you will be doing a POST request with the above body. The request will be fulfilled, 100 Kin will be sent to X and the earn is complete. You now have a working earn in your app! However, it is super easy to sniff out network requests. Just follow these instructions. When you do an earn while watching the request, copy the request and do the above request again and again, until your wallet is empty. You can even increase the amount to do an earn request of 1 million Kin, or more.
Suddenly you get errors that the earn requests fail because there is not enough balance on the wallet where the earns come from! Not good. There needs to be a way to check that your earn is valid. However, this logic cannot be on the app itself, because you can still read the earn request when it leaves the app.
The earn verification logic needs to take place between the request to earn and the actual earn. In a place where the user cannot read out requests or control the behaviour. Always assume that everything coming from a user’s device is 100% insecure, no matter what you are building.
That place is the backend. It’s the only place where you have control over everything and can make sure that earns are valid before doing the actual earn request.
Better way to set up earns
As an example, let’s assume you can only make one earn per day. The following diagram could be a way to set this up:
This is what happens:
- The app sends a request to send 100 Kin to address X to your backend
- The backend checks (in a database) if that address already has earned something today. If yes: send a failed response, because the user already has earned Kin today
- If not: the backend sends a request to the Kin blockchain to send 100 Kin to address X. Then updates the database that this address has earned Kin today. The response is successful and the app is notified
If you now try to sniff out the request and play it out again and again, you will only be able to earn it once a day.
However, it is still possible to circumvent this check quite easily. Just create a new wallet every time before you do the request to your backend. It is very cheap to create a new Kin wallet, so it’s totally possible to send an earn request with address X1, X2, X3, etc, or just create one new wallet Y and as an amount put the amount of Kin you have in your wallet for earns. In one transaction you would lose all Kin that you have.
A good way to prevent all your Kin being stolen in one transaction is to hardcode a limit of the maximum amount of Kin you can earn. If the maximum earn is 100 Kin in your app, every request to earn over 100 Kin is actually invalid. You can add this check to your backend as well, giving you the following diagram:
This is already a lot better than the first try, but we still have the issue of multiple addresses. It is possible to create thousands of Kin addresses and call your backend for 100 Kin for each of those addresses.
Good way to set up earns
To solve the issue of multiple addresses, we can attach an address to a specific device ID. Every Android phone has a unique ID that does not change. When you first open the app and create the wallet, we can save the combination of device ID and wallet in a database. When you do an earn request, don’t send the address to the backend, but the device ID. The backend looks up the address belonging to that device ID and does the other checks already in place. The diagram looks like this:
Now you can still create many Kin addresses, but it’s not possible to send those Kin addresses to the backend for earns. In addition, every device ID can only have one address. If you uninstall and reinstall the app, you don’t get a new device ID. The earn flow is now safe.
However, there is another point that makes the whole flow insecure: the device ID and address are stored together in a database when you first visit the app. So one can try to sniff out that request and register many Kin addresses with bogus device IDs, then use the flow above to send out many earns to those bogus device IDs.
While it becomes more and more difficult to circumvent your security, we can also close this security flaw by implementing SMS verification. This way you can mark device IDs as “verified” once SMS verification is complete. The backend then checks if the device ID in the request is “verified” and will fail if it is not. Google has outstanding documentation on how to implement SMS verification, and this last part is out of scope of this tutorial. Just keep this in mind when actually building the app!
Cold and hot wallet
There’s always a risk that something, somewhere in your application is not secure. To assume the communication with the backend is 100% safe is probably wrong. To minimise the risk of losing all your Kin, it is wise to work with two wallets: a so-called cold and hot wallet.
Say you have 100 million Kin in your wallet available for giving out earns. Then don’t use that wallet to give out earns, but create another wallet and send 1 million Kin to that wallet. The wallet with 99 million Kin is now your cold wallet and the one with 1 million Kin is your hot wallet. The backend will give out earns from your hot wallet.
This way, the maximum amount of Kin you can lose in the absolute worst case scenario is only 1 million Kin. When that happens, identify the problem, fix the security bug and create a new hot wallet (assume that the old hot wallet is compromised). Send 1 million Kin from your cold to your hot wallet and everything is good again. Simple! Just keep a check on the amount of Kin in your hot wallet and top it up once the balance is becoming a bit low.
This concludes the high level security post on earning Kin. In the part 5 we will set up the backend wallet for earns and spends.