IOTA cheques: sending iotas anywhere without requiring a receive address
This is part 4 in this series. I highly suggest reading part 3 about IOTA aliases as well because that will answer some questions that immediately spring up on how to use this easily.
The donation problem
For the longest time one of the problems with IOTA has been the impossibility of having a secure and fixed reusable donation address. This is entirely due to the single-signing nature of IOTA addresses. You cannot simply post an IOTA address and have people send funds there, because once you decide to collect the funds at that address and spend them that address can no longer be used.
With the current wallets protecting against key reuse you will now need to replace the old donation address with a new one.. Which may be difficult to impossible. Imagine having an email signature containing such a donation address. You would have to contact everyone you ever sent email to, to inform them of the new donation address. Not very handy to say the least.
The proposed solution: IOTA cheques
I have often found that solutions to potentially difficult problems can be achieved by turning the problem upside down. And this one was no different.
Who says that the donation recipient is the one that needs to generate the donation address? Why not have the sender generate a fresh address, send the funds there, and then make sure that the receiver can access those funds?
It turns out there is a very easy way to do that with IOTA (or any other crypto currency), You simply send the private key of the fresh address that contains the funds to the recipient. Now he is able to access these funds and send them to his own wallet, leaving the donation address empty. It pretty much functions like sending them an IOTA cheque.
We will see that simply by calling it that way we suddenly open up new ways of looking at this solution. Because now we suddenly realize that we can use this concept for much more than just donations. Writing an IOTA cheque to anyone for any purpose and sending it to them is just a small leap now. It means we no longer require people to provide us with a receive address before being able to send them iotas…
Note that the sender will need a separate space to generate the cheque addresses, to avoid the problem of his wallet accidentally spending the funds in the cheque address. The solution to that is simple: a separate seed. And since we will only use this seed for cheques we will call it our cheque book seed. Every time we want to create an IOTA cheque, we generate a new receive address in our cheque book, and send funds from our wallet to that new cheque address.
The only remaining problem now becomes one of securely sending the private key of the donation address to the recipient. There are a number of ways to achieve this. For example, we could simply email the private key to the recipient. Email is pretty secure overall.
Of course we would prefer more security, because we are sending money. So there is an incentive for people to try and intercept the cheque and cash it for themselves. Luckily we have had ways to do that for a long time now. We can use encryption. Either we use symmetric encryption, and make sure the recipient knows the shared secret encryption key, or the recipient provides us with the public key of an asymmetric key encryption method.
Now we just encrypt the private key with the chosen method, send the encrypted data to the recipient through the medium of our choice, and only he will be able to decrypt it and redeem the IOTA cheque, because only he has the matching decryption key. This means that the message can be sent in the open with no possibility for anyone (well, except maybe the CIA) to hijack the funds through any communication medium.
Improving the usability of IOTA cheques
Now that we have the concept for the solution it becomes a matter of having a good User Experience so that this whole process will be easy to use for any user, whether being the sender or the recipient. Imagine the sender having to manually encrypt the cheque and send the resulting long random byte string to the receiver, who then needs to know that this needs decrypting and how, and then has to import the private key of the cheque in his wallet somehow to redeem the cheque. We definitely need to enlist the help of our wallet software here.
I will discuss 3 ways of creating IOTA cheques that require minimal user interaction in this article. They both require the wallet to do some processing and worst case only one interaction from either user. Both solutions involve IOTA deep links, so you may want to read my article on those.
- Send unprotected. The sender decides that email is safe enough, and asks the wallet to generate an IOTA deep link that the recipient wallet knows how to process and has the wallet send the link by email. The recipient clicks the link, which invokes his wallet app and the wallet will redeem the cheque automatically.
- Send password protected. The sender decides upon a password and communicates it to the receiver. He then asks the wallet to generate a deep link that contains a random value which, combined with the password, will yield the subseed of the cheque address. The sender can now send the link using any public communication medium. The receiver clicks the link, and his wallet will open, ask for the password, and redeem the cheque automatically.
- Use public key encryption. The receiver has provided an IOTA deep link that links to his public key alias. The sender clicks this link (donation link for example) and his wallet will open and ask for some minimal details (amount to send, for example). The sender then presses send and the wallet will automatically create the IOTA cheque and sends the encrypted subseed to the receiver by posting it at the alias address on the Tangle where the recipient wallet will find it automatically and redeem it.
We will now discuss these 3 methods in more detail.
1: Send unprotected
The sender decides that email is safe enough. He opens the Send Cheque screen and provides an email address to send the cheque to. He also provides an amount to send, and possibly a reason. Finally he provides his PIN to allow the wallet to proceed. The wallet will now first generate an IOTA cheque by taking the next address from its cheque book seed and depositing the correct amount of iotas on that address. It may start promoting the address to get it confirmed or leave that to the receiver. Next the wallet generates an IOTA deep link that looks like this:
The kwugfolv9sk….gfdlsn part is actually the 81 trytes of the cheque subseed. The reason part (“Birthday gift”) is the reason the sender provided. Now the wallet creates an email addressed to the provided email address, and makes sure the link is in the message text. It could even add instructions to install the IOTA wallet first when necessary, including links to the app stores. Then it invokes the email program, which allows the user to add more text to the message before he hits send.
Now the recipient receives this email, reads the nice accompanying text, and if necessary clicks an app store link to install the wallet. Then he clicks on the cheque link. His wallet will open and interpret the link. It looks like a cheque link, so it looks at the second part and finds 81 trytes. So it must be a subseed. It decodes the subseed into the address and checks the balance of the address. If zero it checks if it first needs to help confirm the deposit transaction. When non-zero it proceeds to use the subseed to sign off on transferring the funds to an address in its own wallet and makes sure that transaction confirms.
Note that most of what the wallets do here can be done in a background thread or service. There’s no need to block the user from using the wallet for other purposes in the mean time, unless the receiver absolutely needs the funds to send elsewhere.
Note that this method completely depends on the security of your email system. Anyone that intercepts the link can redeem the cheque. Still, for simple use cases this may be a viable method.
2: Send password protected
If we want to secure the subseed from easy interception we will have to protect it by obscuring it somehow. The easy way to obscure it is to protect it with a password. We can send the password separately, through completely different channels if necessary.
Once the password is established, the parties can easily send funds both ways using the same password. Or even use separate passwords for either direction. Whatever they want.
The sender decides he wants to send a pass-word protected IOTA cheque. Now there are 2 possibilities:
- He already connected with this recipient before. In this case all he needs to do is select the recipient from his address book, where the password that was communicated between them is stored.
- He did not connect with this recipient yet. In this case he provides the recipient and the password he communicated to him. The wallet adds those to its address book.
Now the sender can fill in the cheque details, enter his PIN, and share the resulting IOTA deep link with the recipient through any medium. The link will look like this:
These links establish the random input string ks9etgmapj for a specific cheque. The recipient knows what password to use by matching the originator to its address book. If it does not find it in the address book yet, the wallet will ask the user for the password, add it under John Doe in the address book, and then proceeds to redeem the IOTA cheque.
We need the following to pull this off successfully:
- The password to obscure the private key with. Well duh…
Of course we require a minimum length for the password.
- The private key of the address containing the iotas to send.
- A way to match up the password with multiple associated cheques
(an origin identifier).
- An algorithm that obscures the private key by using the password.
- Some measure to prevent someone who manages to intercept the IOTA cheque to easily brute force the password.
The simplest way to obscure the private key is by hashing. In fact, we can set it up so that the data we send, hashed together with the correct password, becomes the private key. This is very easy to do in IOTA, because the (much longer) private key for an address is generated from an 81 tryte sub-seed. So all the sender needs is a random input string, hash it with the password to get such a sub-seed, then use the sub-seed to generate the corresponding receive address, and send the iotas there.
The recipient receives the random input string, uses the same process to hash it with the password, resulting in the sub-seed, and then uses that sub-seed to generate the private key/address pair, so that he can take out the iotas and transfer them to his own wallet.
Next we need an origin identifier, so that we can match up cheques with the correct password in case we receive cheques from multiple sources. We want to use the correct password for the correct cheque, right? There are 2 ways of going about with this. One is just a random identifier, the other is using something that actually identifies the sender, like his email address, which then in turn can be used by the recipient to send funds the other way using the same password. Both methods are useful and do not rule each other out.
Finally, we need an anti brute forcing measure. And we already know such a method, because IOTA uses it as well: Proof of Work. By making the generation of the sub-seed a time-consuming process anyone trying to brute force the password will have to perform PoW for every password permutation he tries before he is able to generate the address from the sub-seed he created and check its balance to see if he found the correct password.
So we require the algorithm that hashes the random input string and the password to result in a sub-seed that ends in a predefined number of zero trits. Currently IOTA requires 14 zeroes in its PoW, which means that on average 3¹⁴ / 2 (close to 2.5 million) hashes of the transaction data are needed to find such a hash.
IOTA uses a nonce field as part of its PoW, but we don’t really need that. It’s perfectly acceptable for both sides (sender and receiver) to do PoW once, so the nonce can be implied in the algorithm. And because we hash a smaller amount of data than an entire transaction we increase the number of zeroes to 15 (about 7 million hashes on average)
Note that contrary to IOTA PoW we are not looking for any hash with 15 zero trits, but for the first hash with 15 zero trits. This is necessary to keep the algorithm deterministic, so that both sender and receiver end up using the same nonce to generate the hash.
Using standard Curl sponge function hashing we run the following algorithm to determine our sub-seed:
- Absorb an 81 tryte nonce, starting with all nines. Incrementing the nonce will be done the same way a seed is incremented, by interpreting the value as having its least significant tryte stored first.
- Absorb the random input string, which is already encoded as trytes, and is padded with nines to 81 trytes.
- Absorb the password. We expect it to be encoded as a UTF-8 string, and will turn that into a tryte string by replacing each byte in the UTF-8 string with 2 trytes: first the high 4 bits (0–15 encoded as A-P), and then the low 4 bits (0–15 encoded as A-P). Pad the result with nines to 81 trytes. This means a password cannot exceed 40 UTF-8 bytes.
- Squeeze out an 81 tryte sub-seed value and check if its last 15 trits are zero. If that is not the case, restart with an incremented nonce value until it does.
- Extra task for the sender: check if the address belonging to the sub-seed already has a balance or has a previous spend on it. If that is the case, generate a new random input string and start from scratch. This last check allows us to keep the random input string limited in length. Using a length of 10 for the random input string gives us over 2 * 10¹⁴ possible sub-seeds for each unique password.
3: Use public key encryption.
The sender decides to make use of the IOTΛlias protocol and post the cheque to either a public (donation) alias or a (previously set up) private alias. He selects the alias from his address book, provides a few details like amount and a reason, enters his PIN, and the wallet will handle everything for him from that point.
The wallet will now first generate an IOTA cheque by taking the next address from its cheque book seed and depositing the correct amount of iotas on that address. It may start promoting the address to get it confirmed or leave that to the receiver. Next the wallet generates an IOTA deep link that looks exactly like the one in use case 1: Send Unprotected:
The kwugfolv9sk….gfdlsn part is again the 81 trytes of the cheque subseed. The reason part (“Birthday gift”) is the reason the sender provided. Now the wallet uses the public key found at the IOTA alias to encrypt the cheque link. Next it will post a zero transaction with this encrypted link as message payload at the alias address. The receiver’s wallet will find it there, decrypt it with the private key for the alias, and redeem the cheque automatically.
Note that in this case the receiver does not have to do anything at all. His wallet will automatically redeem any cheque received whenever it is active.
Well, here you have it. A way to send iotas to anyone, anywhere without requiring them to generate and provide a receive address, without the risk of address reuse, and through pretty much any communication medium you can think of. It uses the IOTA deep linking protocol to minimize user interaction, and can leverage the IOTΛlias protocol to not even have to bother the receiver at all.
Feel free to comment on this article or contact me on Discord (@Eric Hop) or my IOTA Facebook group (https://www.facebook.com/groups/iotatangle) to discuss this protocol more.