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
Docs > The API >
signup
POST | https://keybase.io/_/api/1.0/signup.json
|
|
SAMPLE PARAMS |
name: "Chris" # required
email: "cc@chriscoyne.com" # required
username: "chris" # required
pwh: "aabbccee..." # required
pwh_version: 3 # required
salt: "7d34343eeeee..." # required
invitation_id: "0000000000123" # required...for now
pdpka5_kid: "0120aabb....." # required
|
|
SAMPLE OUTPUT |
{
"status": {
"code": 0
},
"csrf_token": "lgHZIDFjZmY0Nzlj..."
}
|
|
WATCH FOR | "BAD_SIGNUP_USERNAME_TAKEN"
"BAD_SIGNUP_USERNAME_DELETED"
"BAD_SIGNUP_USERNAME_RESERVED"
"BAD_SIGNUP_EMAIL_TAKEN"
"BAD_SIGNUP_TEAM_NAME"
"INPUT_ERROR"
|
Picking a salt
It is the client app's responsibility to generate a salt.
Make sure to use a
strong pseudo-random number generator. In the browser, for example, we collect entropy
from a combination of window.crypto.getRandomValues
and a bunch of extra CPU timing.
Your salt should be a 16-byte number, hex encoded. In other words, it should be sent to Keybase as a 32-character hex string.
Generating the password hash (pwh) and PDPKA5 Key (pdpka5_kid)
For these two fields, compute:
passphraseStream = scrypt(passphrase, unhex(salt), N=215, r=8, p=1, dkLen=256)
pwh = passphraseStream[192:224]
v5 = passphraseStream[224:256]
pdpka5_kid = keybaseKID(edDSAPublicKeyFromSeed(v5))
That is, we stretch the input passphrase using the salt generated on signup.
One slice of the output stream is interpreted directly as pwh
, the legacy
passphrase hash. It's more or less ignored on the server. The next slice is
treated like an EdDSA private key, and
the corresponding public key is sent to the server in Keybase key ID format. See the login API call for more details on how this
is used later for logins.