edits
This commit is contained in:
parent
b2f6e290d1
commit
3d4336bab7
@ -2,14 +2,17 @@
|
||||
|
||||
How to support [RFC 6238](https://www.rfc-editor.org/rfc/rfc6238)
|
||||
TOTP (Time based One Time Password) 2FA check, on our little embedded
|
||||
device without a clock?
|
||||
device without a real-time clock?
|
||||
|
||||
Solution: Store the preshared secret in the Colcard, and send that
|
||||
Solution: Store the pre-shared secret in the Coldcard, and send that
|
||||
securely to a trusted webserver which knows the time and can do a
|
||||
fancy UX. The backend accepts the numeric code and reveals a secret
|
||||
that can be used back on the Coldcard to authorize an action.
|
||||
|
||||
## History / Background
|
||||
For the Mk4, the secret is 8 digit numeric code to be entered,
|
||||
for the COLDCARD Q, it is a QR code to be scanned.
|
||||
|
||||
### History / Background
|
||||
|
||||
The HSM feature uses HOTP tokens, which do not require a backend,
|
||||
but are not as robust as time-based tokens.
|
||||
@ -22,40 +25,44 @@ but we may find other uses for it.
|
||||
- Web backend has a ECC keypair, with pubkey known to CC firmware releases.
|
||||
- Usual 2fa base32 secret is picked by CC and stored in CC (so that server is stateless)
|
||||
- CC creates URL encrypted to the pubkey of server, containing args:
|
||||
- shared secret
|
||||
- the good nonce (16 bytes, or only 8 decimal digits for Mk4) to be provided back
|
||||
- shared secret for TOTP (same value as held in user's phone)
|
||||
- the response nonce (16 bytes, or 8 digits for Mk4) to be revealed to the user
|
||||
on successful auth
|
||||
- flag if Q model, so can provide a QR to be scanned in that case (rather than digits)
|
||||
- some text label for what's being approved [presented to user so they can pick
|
||||
correct 2fa shared secret]
|
||||
- above is all encrypted in the URL.
|
||||
- some text label for what's being approved, which is presented to user so they can pick
|
||||
correct 2fa shared secret.
|
||||
- above is all encrypted in transit, and only the server can decrypt
|
||||
- user is sent to that encrypted URL using NFC tap on the Coldcard
|
||||
- user arrives at server:
|
||||
- shown label [which also indicates the server can be trusted, since only it could decrypt it]
|
||||
- prompt for 6 digits from authenticator app
|
||||
- does [RFC 6238](https://www.rfc-editor.org/rfc/rfc6238) 2FA check
|
||||
- does [RFC 6238](https://www.rfc-editor.org/rfc/rfc6238) 2FA check using current time
|
||||
- checks using current time and the shared secret provided by CC, fails if wrong.
|
||||
- time based failure: offer retry (they typed too slow / minor clock drift)
|
||||
- can offer to retry, but also do some rate limiting (only one attempt per 30-sec period)
|
||||
- server will store very recent responses so attacker cannot get two codes
|
||||
in any 30sec period (ie. blocks immediate reuse of same URL)
|
||||
- if Q, show a QR code to be scanned, with the full nonce
|
||||
- for non-Q system, a 8-digit decimal value is given: user has to enter that into the Coldcard
|
||||
- web site shows instructions about what to do next on product.
|
||||
- until a valid code is given, user is stuck here
|
||||
- when valid token received:
|
||||
- if Q, show a QR code to be scanned, with the full nonce
|
||||
- for non-Q system, a 8-digit decimal value is given: user has to enter that into the Coldcard
|
||||
- web site shows instructions about what to do next on product.
|
||||
|
||||
## From Coldcard PoV
|
||||
|
||||
- makes complex encrypted URL, waits for number back (or QR)
|
||||
- makes complex encrypted URL, which contains a nonce it wants, waits for that nonce back (or QR)
|
||||
- it's either the nonce from the URL, or fail
|
||||
- if the good nonce, then we know the server knows our shared secret and we
|
||||
are trusting it actually verify the 2FA token.
|
||||
- if the right nonce, then we know the server knows the decryption key, and we
|
||||
are trusting it actually verify the 2FA token properly.
|
||||
|
||||
## Encryption - Simple ECDH
|
||||
|
||||
- CC picks a secp256k1 keypair, generates compressed pubkey
|
||||
- multiplies that by server's known public key, sha256(that coordinate) is the session key
|
||||
- multiplies that private key by server's known public key
|
||||
- apply sha256(resulting coordinate) => the session key
|
||||
- apply AES-256-CTR over URL contents (ascii text)
|
||||
- prepend 33 bytes of pubkey, and base64url encode the result
|
||||
- prepend 33 bytes of pubkey, and base64url encode all of it
|
||||
- full url is: `https://coldcard.com/2fa?{base64 encoded binary}`
|
||||
|
||||
## Trust Issues
|
||||
|
||||
@ -66,6 +73,8 @@ but we may find other uses for it.
|
||||
- Only we can run the server, because the private key is company-secret.
|
||||
- MiTM and network snoopers get nothing because HTTPS is used and only your browser
|
||||
can see the nonce, and only after you've given the right digits.
|
||||
- Coinkite server could skip the 2FA checks and just give you the answer
|
||||
you want to type into the Coldcard. Again, you have to trust us on that.
|
||||
|
||||
## URL Format
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user