Zk2FA: Private keys suck!
Mr.FreemanPrivate keys are a nightmare for WEB3 users, even the experienced ones. With an ongoing improvement in Quantum computing and malwares, more and more users will loose their funds due to private key leakage. Let's be honest, Haven't you backed up your mnemonic keys in your phone gallery or in your Telegram Saved Message chat? I'm sure many of you do.
So people always had to either use Custodian Wallets(Even more dangerous choice) or had to use Physical Devices(Ledger e.g.) to store funds(which also has many risky aspects). But Zk2FA has came to change this situation. A fully secure on-chain design, without any relying on third party API or trusted parties.
So Let's dive a bit deeper in Zk2FA architecture.
What is TOTP two step authentication?
Have you ever used Google/Microsoft authenticator? Those apps allow you to generate an OTP code that is regenerated every 30 seconds. I won't get into the details of this method but the beauty of this method is that you can predict exactly your OTP code in 9 years and 4 months and 3 days and 2 hours and 17 minutes and 34 seconds later.
What is Extensions and why Zk2FA only works on W5?
W5 is a Smart Contract wallet developed by Tonkeeper team, that allows turning off signatures and also allows extensions to fully manage the smart contract. Extensions are some arbitrary smart contract that in our case is this one, Which we called it Zk2FA.
You can read more about W5 and extensions here.
In Zk2FA you trust a smart contract code to setup a 2-step authentication(2FA) mechanism on your wallet.
Zk2FA uses TOTP, but how?
So as I mentioned this OTP code is predictable if you have a secret key(the QR code that you scan when setting up your 2fa). In Zk2FA when you are setting up your personal Zk2FA contract, you calculate every OTP code for the foreseeable future, and form a Merkle tree and only put the root of this tree in your Zk2FA contract.

so Let's say after 7 days you are trying to pass the otp challenge on the Zk2FA contract, so you will calculate the MiMchash(1735214078000, 666666) and find it in your Merkle tree and use this Circuit and calculate a proof so you can prove it on the Zk2FA contract that you know the correct/valid OTP code but you won't reveal it.
An OTP tree for 1 month has a size of ~2^17 and an OTP tree for a year has a size of 2^21.
Business plan 😁: This means that the owner of wallet has to buy a subscription package for this service so that they they can refresh the OTP code once a while:)
Is this Merkle Tree Private data?
YES. If your Merkle tree is shared with someone, and they also have your private key, then it's possible for them to do a brute force and find an OTP code in some specific time in future(not very easy but possible:)
Why ZK in Zk2FA?
Let's say you decided to use normal merkle tree proof similar to HMSTR contract and proof inclusion of the leaf in the tree then you have to broadcast your OTP code on-chain and if someone who knows your private key watched over the mempool, they can use your OTP code and replace your transaction. So sending your OTP code to the contract is not an option. Unless there is a way to prove our OTP code without revealing it. Proving without revealing is the definition of ZK. That's why we use ZK. Also calculating a proof is way faster than the normal merkle proof that is use in built-in TON Merkle proof mechanism.
External Mode vs Internal Mode
Let's say you made your Zk2FA proof and everything is ready to send your transaction. The ideal and easiest way is to use External mode, which is the default mode for Zk2FA. In this mode you will send an OTP proof and your actions list(refer to W5 actions) to the Zk2FA contract with external message(all of the message is signed with your private key) and after validation of signature the message is accepted and the Zk2FA contract will check the OTP proof and if that also passes, then you will be able to send your actions(or disable/change the OTP). If your private key is leaked, then someone could try to send some actions to drain your funds but without an OTP proof they have no chance, and if they send the correct format for OTP proof(with wrong data) then they have 3 attempts and if they fail 3 times in a row then the Zk2FA contract will switch to the Internal mode.
Question: Why do you accept message before checking the proof? The reason is TON only allocates 10,000 Gas limit by default to external messages, and checking ZK proof will surpass the limit, so I have to accept the message(after checking sign).
Internal Mode in Zk2FA
In the Contract code we call it Emergency Mode, in this mode the contract won't accept any external message(to avoid gas leakage in the Zk2FA contract). If we are in this mode, the owner knows that their private key is leaked so they have to withdraw their funds and assets from the wallet with internal message and an OTP proof to authenticate.
In this mode the owner of OTP proof has the option to change the public key of their wallet with a new mnemonic phrase so that their leaked private key is no longer usable by the attacker.
Setup Flow
The Experience to set up the Zk2FA is simple, users will generate a random secret for the TOTP on their client and they will scan and add it to their Authenticator app and then they will sign a transaction and add the Zk2FA contract address to their extension list, and then they will deploy their Zk2FA contract and once it deploys it will automatically setup itself as the guardian of the W5 wallet.
What will happen now?
The signature will be disabled on W5 wallet and user won't be able to just sign and send the transaction directly. They need to sign and also attach an OTP proof to Zk2FA contract and it will check the sign and proof and only then will send the transaction to w5 to be executed.
What if I loose access to my Authenticator app?
Most of these apps have cloud backups but even if you do loose your access then your only option is to wait until your Zk2FA subscription period is finished and then you can just simply use your sign to disable/replace your OTP.
Two-step Sign User Flow
If the Zk2FA is active on your wallet, you will simply insert your OTP code and just wait a few seconds to import your Merkle Tree(from local storage or downloading it from your wallet provider server or in worst case generate it again by exporting the Secret from your authenticator app) and then generate a ZK proof and sign all the payload and send it all together. The only user interaction will be inserting the 6 digit code for Zk2FA which is not very inconvenient and the rest is done in the background with ZK magic.
Improvement Ideas
2. Add some kind of Guardian wallet to recover your wallet in case you loose access to your OTP generator(not very safe).
3. An interface to setup and use Zk2FA(coming soon on TONNEL.Network)
if you have any idea you can share it with @tonnel or create a PR/Issue on the github
. . . . . . . . . . . . . . .
Please follow us on our social channels to get the latest update on TONNEL Network & ZK2FA
Telegram Channel: https://t.me/tonnel_en
Telegram Channel: https://t.me/zk2fa
Telegram Chat(English): https://t.me/tonnel_chat
Telegram Chat(Russian): https://t.me/tonnel_chat_ru
Website: https://tonnel.network
Email: freeman@tonnel.network