Save key salts after auth

The key salts endpoint can only be accessed right after authentication, it's
blocked after auth refresh.

Closes: https://github.com/emersion/hydroxide/issues/68
This commit is contained in:
Simon Ser 2019-08-31 17:43:46 +03:00
parent 2de4f13dc4
commit cc03e059b9
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
3 changed files with 19 additions and 14 deletions

View File

@ -25,6 +25,7 @@ type CachedAuth struct {
protonmail.Auth protonmail.Auth
LoginPassword string LoginPassword string
MailboxPassword string MailboxPassword string
KeySalts map[string][]byte
// TODO: add padding // TODO: add padding
} }
@ -131,7 +132,7 @@ func authenticate(c *protonmail.Client, cachedAuth *CachedAuth, username string)
} }
cachedAuth.Auth = *auth cachedAuth.Auth = *auth
return c.Unlock(auth, cachedAuth.MailboxPassword) return c.Unlock(auth, cachedAuth.KeySalts, cachedAuth.MailboxPassword)
} }
func ListUsernames() ([]string, error) { func ListUsernames() ([]string, error) {

View File

@ -184,7 +184,12 @@ func main() {
} }
} }
_, err := c.Unlock(a, mailboxPassword) keySalts, err := c.ListKeySalts()
if err != nil {
log.Fatal(err)
}
_, err = c.Unlock(a, keySalts, mailboxPassword)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -195,9 +200,10 @@ func main() {
} }
err = auth.EncryptAndSave(&auth.CachedAuth{ err = auth.EncryptAndSave(&auth.CachedAuth{
*a, Auth: *a,
loginPassword, LoginPassword: loginPassword,
mailboxPassword, MailboxPassword: mailboxPassword,
KeySalts: keySalts,
}, username, secretKey) }, username, secretKey)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -141,7 +141,10 @@ func (c *Client) Auth(username, password, twoFactorCode string, info *AuthInfo)
return nil, err return nil, err
} }
return respData.auth(), nil auth := respData.auth()
c.uid = auth.UID
c.accessToken = auth.AccessToken
return auth, nil
} }
type authRefreshReq struct { type authRefreshReq struct {
@ -178,7 +181,7 @@ func (c *Client) AuthRefresh(expiredAuth *Auth) (*Auth, error) {
return auth, nil return auth, nil
} }
func (c *Client) listKeySalts() (map[string][]byte, error) { func (c *Client) ListKeySalts() (map[string][]byte, error) {
req, err := c.newRequest(http.MethodGet, "/keys/salts", nil) req, err := c.newRequest(http.MethodGet, "/keys/salts", nil)
if err != nil { if err != nil {
return nil, err return nil, err
@ -235,7 +238,7 @@ func unlockKey(e *openpgp.Entity, passphraseBytes []byte) error {
return nil return nil
} }
func (c *Client) Unlock(auth *Auth, passphrase string) (openpgp.EntityList, error) { func (c *Client) Unlock(auth *Auth, keySalts map[string][]byte, passphrase string) (openpgp.EntityList, error) {
c.uid = auth.UID c.uid = auth.UID
c.accessToken = auth.AccessToken c.accessToken = auth.AccessToken
@ -244,11 +247,6 @@ func (c *Client) Unlock(auth *Auth, passphrase string) (openpgp.EntityList, erro
return nil, err return nil, err
} }
salts, err := c.listKeySalts()
if err != nil {
return nil, err
}
var keyRing openpgp.EntityList var keyRing openpgp.EntityList
for _, addr := range addrs { for _, addr := range addrs {
for _, key := range addr.Keys { for _, key := range addr.Keys {
@ -259,7 +257,7 @@ func (c *Client) Unlock(auth *Auth, passphrase string) (openpgp.EntityList, erro
} }
passphraseBytes := []byte(passphrase) passphraseBytes := []byte(passphrase)
if keySalt, ok := salts[key.ID]; ok && keySalt != nil { if keySalt, ok := keySalts[key.ID]; ok && keySalt != nil {
passphraseBytes, err = computeKeyPassword(passphraseBytes, keySalt) passphraseBytes, err = computeKeyPassword(passphraseBytes, keySalt)
if err != nil { if err != nil {
return nil, err return nil, err