Attention: Mt.Gox, TradeHill, MyBitCoin, and all other bitcoin services!Here is an idea for an easy way to add optional
2-factor authentication to logins.
Two-factor authentication is a more secure way of allowing access to a user account. It uses two separate channels to ensure that the user is who they say they are. Typically, it uses something they know (like a password), and something they have (like an RSA key fob). The problem with key fobs is that you have to pay for the third-party hardware gadget, and distribute them to users, which gets complicated.
The simple alternative I'm suggesting is this: allow the user an option to use 2-factor authentication based on a 260-character "passcard" that the user provides, which is then used at login to issue a challenge-response PIN identification.
https://secure.wikimedia.org/wikipedia/en/wiki/Two-factor_authentication https://secure.wikimedia.org/wikipedia/en/wiki/Challenge_responseHere's how it works.
(1) To set up my 2-factor login, I send you a string of 260 symbols, to be interpreted as a passcard with 10 rows (0-9) and 26 columns (A-Z). You store that safely, like you do (hopefully) with passwords. This passcard information is communicated only once, when I'm setting up the 2-factor login (much like setting a password).
(2) Now each time I login, you include a request for a 4-digit PIN, starting at a particular row and column (generated randomly). For example:
User ID: ____________________
Password: ____________________
PIN at 4V: ____
The key point here is that a hacker (say, hypothetically, in Hong Kong) won't have access to my passcard, and can't login as if they were me, even if they've cracked my password. [Added bonus: kills bots dead. No need for annoying CAPTCHAs if they've opted for 2-factor login.]
For my part, I can create my 260-symbol passcard in whatever way I want. For example, I can use the Python code below to convert a strong passphrase into a passcard block (maybe on a different computer, just to be extra safe). Now I can print out the passcard, put it in my wallet, and erase all traces of its creation. If I ever lose the card, I can easily re-create it from the passphrase. (Python uses the Mersenne Twister RNG algorithm, so it will always generate the same sequence from the given seed).
Or, if using that piece of paper is too cumbersome for me, I might decide to have a .jpg image of the passcard on my phone, or whatever other reference method I'm comfortable with. [Or, if I'm not too concerned about someone gaining full access to my computer, I could even have it on my desktop, or have a password manager that answers the challenge-response PIN for me.]
Python code and example:
# Victor's two-factor authentication passcard generator
# (c) copyright: Victor Egan, 1EWD8L6ujFQMDiDn8Se9SP9A4yaxwpbRks
from random import randint, seed
symbols = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ@#$%&*<>+{}[]()/?'
def generate_passcard (passphrase, symbols):
"""Generate the 260-character passcard block for the given passphrase"""
passcard = ''
seed(passphrase)
for i in range(260):
s = symbols[randint(0, len(symbols) - 1)]
passcard += s
return passcard
def print_passcard (passcard):
"""Print the given 260-character passcard"""
print '\nPasscard block:', passcard
print
print ' ABCDEFGHIJKLMNOPQRSTUVWXYZ'
print '----------------------------'
cardlist = list(passcard)
for i in range(10):
line = ''
for j in range(26):
line += cardlist.pop(0)
print i, line
print
return
Note: this is not a very good passphrase, it's just being used as an example.
>>> passphrase = "Roger Roger, you have clearance Clarence, what's your vector Victor?"
>>> passcard = generate_passcard(passphrase, symbols)
>>> print_passcard(passcard)
Passcard block: sL#tyHqrY4b+mw+VU[VAr[GpQHKaVz3eza3m4#zWJfPBXU)yw[W7Bj]V%s48GSLP?+2YeN4eJa)fWPg?PAGQByWhTgXWkc#b*VaV>/9a9W*u$#TR&A9zq(xPzVN2tfxpk8sz#kE+CN+GbyDqm&Y#Y%a6RTxv5?gqP{yYMZaZB?+/&Lb8r8Lj}h*DcBVk(?738Nru(/>XsBB2pw>errsEzXKAdRMcd
ABCDEFGHIJKLMNOPQRSTUVWXYZ
----------------------------
0 sL#tyHqrY4b+mw+VU[VAr[GpQH
1 KaVz3eza3m4#zWJfPBXU)yw[W7
2 Bj]V%s48GSLP?+2YeN4eJa)fWP
3 g?PAGQByWhTgXWkc#b*VaV>/9a
4 9W*u$#TR&A9zq(xPzVN2tfxpk8
5 sz#kE+CN+GbyDqm&Y#Y%a6RTx<
6 Ezs8#)7+frvy})sUZkrFxBH+KH
7 9k4EU9u>v5?gqP{yYMZaZB?8 >+/&Lb8r8Lj}h*DcBVk(?738Nr
9 u(/>XsBB2pw>errsEzXKAdRMcd
Example login:
User ID: vectorvictor
Password: ****************
PIN at 8Y: **** Nr>+
People: If you want to use this code to create a passcard, go ahead.
Businesses: If you want to use this code to help your users create their passcard, please ask me for permission first. Regardless, do allow them to submit *any* block of 260 symbols that they choose.
Note: I do not suggest using a card like this for all of your passwords, because it is a single point of failure, and only provides a relatively small number of possible passwords. (It would be better than reusing the same weak passwords, however). As a second channel for authentication, it seems okay.
For some more fun facts on password cracking (and on the Mt.Gox hack in particular) see my previous post:
http://forum.bitcoin.org/index.php?topic=24727.msg314393#msg314393Disclaimer: I'm a math and algorithms guy, but I don't know very much about computer security or cryptography. This whole idea might be horribly broken. If it is, then please explain why, so that we can come up with something better.