When it came time to implement 2FA in my open-source project Mentat, I wanted to try something a little different. As an end-to-end encrypted chat app, asymmetric encryption was already an important aspect of the platform, and was easy enough to implement using OpenPGP.js. When a user signs up for the platform, a keypair is generated and the public key is saved in the database as part of that user's identity. But an issue arises when the user wants to sign into a different device: how can the user's private key be transmitted in a way that doesn't reveal their credentials to the server? As it turns out, I was able to solve this issue and add a second authentication factor in the same step.