Overview
Calls
- •signup
- •getsalt
- •login
- cors•user/lookup
- cors•<user>/pgp_keys.asc
- •key/add
- •key/fetch
- •session/killall
- •sig/next_seqno
- •sig/post
- •sig/post_auth
- cors•merkle/root
- cors•merkle/block
Other details
login
POST | https://keybase.io/_/api/1.0/login.json
|
|
SAMPLE PARAMS |
email_or_username: 'u6755dc4f',
pdpka5: "g6Rib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgbyBuVXsJzAkRjK4mAmHNvtOKhyHKSonMiRWg7La+KI4Kp3BheWxvYWTFAbd7ImJvZHkiOnsiYXV0aCI6eyJub25jZSI6ImVkYTA5MjFhYjg5NzkzMGZiODc0OTFjZjlmOTczNGVmIiwic2Vzc2lvbiI6ImxnSFpJRFF4WVRGa09HSTJObUprWXpkall6aGtPRGswTnpCaVlXVmtNV1F6TkRFNXpsZ0ZkeTNOQ1dEQXhDQW1jN2QrcmNkSGZPYWRtUjJVN2xTRko2NzJtY1Q3RmxBNG5Vc2cycEhRNGc9PSJ9LCJrZXkiOnsiaG9zdCI6ImtleWJhc2UuaW8iLCJraWQiOiIwMTIwNmYyMDZlNTU3YjA5Y2MwOTExOGNhZTI2MDI2MWNkYmVkMzhhODcyMWNhNGE4OWNjODkxNWEwZWNiNmJlMjg4ZTBhIiwidWlkIjoiNDFhMWQ4YjY2YmRjN2NjOGQ4OTQ3MGJhZWQxZDM0MTkiLCJ1c2VybmFtZSI6InU2NzU1ZGM0ZiJ9LCJ0eXBlIjoiYXV0aCIsInZlcnNpb24iOjF9LCJjdGltZSI6MTQ3Njc1MzE5NywiZXhwaXJlX2luIjoxNTc2ODAwMDAsInRhZyI6InNpZ25hdHVyZSJ9o3NpZ8RALfJuyhIs/4CIIHi6WpF0sB1GFXH+yVGBztPp5QeqFAIZ4ycUPYGKmtLbR4NxcQHq2d4OTPblwHwoPWdrkawoC6hzaWdfdHlwZSCjdGFnzQICp3ZlcnNpb24B"
pdpka4: "g6Rib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgTnrhJensoHhID/9vyD+KYm6e+9qDfdbFrB5sjg6YZDUKp3BheWxvYWTFAbd7ImJvZHkiOnsiYXV0aCI6eyJub25jZSI6IjE3ZGVkZTg2MjM1M2I5NWI3ODVlMTUyMDhiZWNmYTZjIiwic2Vzc2lvbiI6ImxnSFpJRFF4WVRGa09HSTJObUprWXpkall6aGtPRGswTnpCaVlXVmtNV1F6TkRFNXpsZ0ZkeTNOQ1dEQXhDQW1jN2QrcmNkSGZPYWRtUjJVN2xTRko2NzJtY1Q3RmxBNG5Vc2cycEhRNGc9PSJ9LCJrZXkiOnsiaG9zdCI6ImtleWJhc2UuaW8iLCJraWQiOiIwMTIwNGU3YWUxMjVlOWVjYTA3ODQ4MGZmZjZmYzgzZjhhNjI2ZTllZmJkYTgzN2RkNmM1YWMxZTZjOGUwZTk4NjQzNTBhIiwidWlkIjoiNDFhMWQ4YjY2YmRjN2NjOGQ4OTQ3MGJhZWQxZDM0MTkiLCJ1c2VybmFtZSI6InU2NzU1ZGM0ZiJ9LCJ0eXBlIjoiYXV0aCIsInZlcnNpb24iOjF9LCJjdGltZSI6MTQ3Njc1MzE5NywiZXhwaXJlX2luIjoxNTc2ODAwMDAsInRhZyI6InNpZ25hdHVyZSJ9o3NpZ8RAY24jVxf/661fILLrRwsfC6/dY102bGPiKCWcYTNLAYR6YZXBP7UstNktpkz7Ymjt9HVZwgVvPxtOpUO8Wne3BKhzaWdfdHlwZSCjdGFnzQICp3ZlcnNpb24B"
|
|
SAMPLE OUTPUT |
{
"status": {
"code": 0,
"name": "OK"
},
"session": "lgHZIDU1YzA3OWJmNWYx...",
"me": "/* {user object} */"
}
|
|
WATCH FOR | "BAD_LOGIN_PASSWORD"
"BAD_LOGIN_USER_NOT_FOUND"
|
Round 2 of the 2-Round Login Protocol
In the first round, the client called getsalt
to retrieve a salt and a login_session
token.
In this, the second round of the protocol, the client computes the password hash. The password hash is a function of the UTF-8 password, and the binary encoding of the salt (which was returned in hex from the server). The first 192 bytes of output are used for secret-key encryption elsewhere in the site, so they are ignored here. Bytes 192 through 256 of this output are used to authenticate the user during login:
passphraseStream = scrypt(passphrase, unhex(salt), N=215, r=8, p=1, dkLen=256)
v4 = passphraseStream[192:224]
v5 = passphraseStream[224:256]
At first, let's cover version 5 of the protocol, and then we'll
go back and cover version 4 below. The 32-byte slice of the
passphrase stream (v5
above) is intepreted as an EdDSA private key. The server
knows the corresponding public key. The client proves knowledge of this
secret key by making a signature that the server can verify.
The client should sign a JSON blob of the form:
{ "body": { "auth": { "nonce": "ab68b24b6bcff3dc6e0cdc558e3e043c", "session": "lgG5dGhlbWF4KzhkY2FhNjc4QGdtYWlsLmNvbc5YBShhzQlgwMQgtABibipP7sQIpLv/hO+akJ5mdrD64QkuhY08VdLwtW0=" }, "key": { "host": "keybase.io", "kid": "0120fffa77faf7c189edbb82a942c5feef831335ced44e2fd3155673b023314719070a", "username": "u5c7d0817" }, "type": "auth", "version": 1 }, "ctime": 1476733025, "expire_in": 157680000, "tag": "signature" }The relevant fields are:
-
nonce
: a random 16-byte nonce generated by the client that once accepted cannot be replayed -
session
: returned fromgetsalt
in the previous stage of the login flow -
host
: alwayskeybase.io
-
kid
: the key ID of the public key that will verify this signature -
username
: the username who is trying to login. If the login is done via email, this field will be absent and anemail
field will be present with the intended email address -
ctime
: the UTC-time when this signature was generated -
expire_in
: how long this signature is good for; after it expires, it will not be admissable for login
The client then computes the EdDSA signature of this JSON blob (stringified with minimal white space), and
packages the result as a Keybase-style signature.
The result is posted to the server as the pdpka5
parameter (note that "PDPKA" stands
for Passphrase-Derived Public Key Authentication).
As for the slight complication we hinted at above, clients should log in with
both Version 4 and Version 5 of the protocol at the same time. The only differences
between the two are that: (1) the secret key is derived from a different slice
of the passphrase stream --- v4
versus v5
above; and
(2) that the result is posted as the HTTP parameter pdpka4
in the
V4 login system and as pdpka5
in the V5 login system.
The first time a user logs in with this scheme, the server captures the V5 public key and requires this version for all subsequent logins. It checks V4 to make sure the user is authorized. We encourage all logins use V4 and V5 simultaneously, so the current login works, and the user is upgraded going forward.
Session cookie
A successful login will reply with a session
cookie.
The user object "me"
Upon login, you'll get back a user object. Your user object is a large dictionary and contains pretty much everything about you and your account. (See the user objects page in the documentation for more info.)