Store both masterKey and secretKey

This commit is contained in:
Neeraj Gupta 2023-09-22 17:48:14 +05:30
parent b4f0994a34
commit 652cf53e32
6 changed files with 46 additions and 32 deletions

View file

@ -54,12 +54,12 @@ func (c *ClICtrl) AddAccount(cxt context.Context) {
if authResponse.EncryptedToken == "" || authResponse.KeyAttributes == nil {
panic("no encrypted token or keyAttributes")
}
masterKey, token, decErr := c.decryptMasterKeyAndToken(cxt, authResponse, keyEncKey)
secretInfo, decErr := c.decryptMasterKeyAndToken(cxt, authResponse, keyEncKey)
if decErr != nil {
flowErr = decErr
return
}
err := c.storeAccount(cxt, email, authResponse.ID, app, masterKey, token)
err := c.storeAccount(cxt, email, authResponse.ID, app, secretInfo)
if err != nil {
flowErr = err
return
@ -68,7 +68,7 @@ func (c *ClICtrl) AddAccount(cxt context.Context) {
}
}
func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, app api.App, masterKey, token []byte) error {
func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, app api.App, secretInfo *accSecretInfo) error {
// get password
secret := GetOrCreateClISecret()
err := c.DB.Update(func(tx *bolt.Tx) error {
@ -79,8 +79,9 @@ func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, ap
accInfo := model.Account{
Email: email,
UserID: userID,
MasterKey: *model.MakeEncString(string(masterKey), secret),
Token: *model.MakeEncString(string(token), secret),
MasterKey: *model.MakeEncString(string(secretInfo.MasterKey), secret),
Token: *model.MakeEncString(string(secretInfo.Token), secret),
SecretKey: *model.MakeEncString(string(secretInfo.SecretKey), secret),
App: app,
}
accInfoBytes, err := json.Marshal(accInfo)

View file

@ -10,6 +10,7 @@ type Account struct {
UserID int64 `json:"userID" binding:"required"`
App api.App `json:"app" binding:"required"`
MasterKey EncString `json:"masterKey" binding:"required"`
SecretKey EncString `json:"secretKey" binding:"required"`
Token EncString `json:"token" binding:"required"`
}

View file

@ -17,15 +17,15 @@ func MakeEncString(plainText string, key []byte) *EncString {
log.Fatalf("failed to encrypt %s", err)
}
return &EncString{
CipherText: utils.BytesToBase64(cipher),
Nonce: utils.BytesToBase64(nonce),
CipherText: utils.EncodeBase64(cipher),
Nonce: utils.EncodeBase64(nonce),
}
}
func (e *EncString) MustDecrypt(key []byte) string {
plainBytes, err := crypto.DecryptChaCha20poly1305(utils.Base64DecodeString(e.CipherText), key, utils.Base64DecodeString(e.Nonce))
plainBytes, err := crypto.DecryptChaCha20poly1305(utils.DecodeBase64(e.CipherText), key, utils.DecodeBase64(e.Nonce))
if err != nil {
panic(err)
}
return utils.BytesToBase64(plainBytes)
return utils.EncodeBase64(plainBytes)
}

View file

@ -18,7 +18,7 @@ func (c *ClICtrl) SyncAccount(account model.Account) error {
return err
}
token := account.Token.MustDecrypt(cliSecret)
urlEncodedToken := base64.URLEncoding.EncodeToString(utils.Base64DecodeString(token))
urlEncodedToken := base64.URLEncoding.EncodeToString(utils.DecodeBase64(token))
c.Client.AddToken(account.AccountKey(), urlEncodedToken)
ctx := c.GetRequestContext(context.Background(), account)
return c.syncRemoteCollections(ctx, account)

View file

@ -11,6 +11,12 @@ import (
"github.com/kong/go-srp"
)
type accSecretInfo struct {
MasterKey []byte
SecretKey []byte
Token []byte
}
func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *api.SRPAttributes) (*api.AuthorizationResponse, []byte, error) {
for {
// CLI prompt for password
@ -28,18 +34,18 @@ func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *
srpParams := srp.GetParams(4096)
identify := []byte(srpAttr.SRPUserID.String())
salt := utils.Base64DecodeString(srpAttr.SRPSalt)
salt := utils.DecodeBase64(srpAttr.SRPSalt)
clientSecret := srp.GenKey()
srpClient := srp.NewClient(srpParams, salt, identify, loginKey, clientSecret)
clientA := srpClient.ComputeA()
session, err := c.Client.CreateSRPSession(ctx, srpAttr.SRPUserID, utils.BytesToBase64(clientA))
session, err := c.Client.CreateSRPSession(ctx, srpAttr.SRPUserID, utils.EncodeBase64(clientA))
if err != nil {
return nil, nil, err
}
serverB := session.SRPB
srpClient.SetB(utils.Base64DecodeString(serverB))
srpClient.SetB(utils.DecodeBase64(serverB))
clientM := srpClient.ComputeM1()
authResp, err := c.Client.VerifySRPSession(ctx, srpAttr.SRPUserID, session.SessionID, utils.BytesToBase64(clientM))
authResp, err := c.Client.VerifySRPSession(ctx, srpAttr.SRPUserID, session.SessionID, utils.EncodeBase64(clientM))
if err != nil {
log.Printf("failed to verify %v", err)
continue
@ -55,60 +61,66 @@ func (c *ClICtrl) decryptMasterKeyAndToken(
_ context.Context,
authResp *api.AuthorizationResponse,
keyEncKey []byte,
) (masterKey, token []byte, err error) {
) (*accSecretInfo, error) {
var currentKeyEncKey []byte
var masterKey, secretKey, tokenKey []byte
var err error
for {
if keyEncKey == nil {
// CLI prompt for password
password, flowErr := GetSensitiveField("Enter password")
if flowErr != nil {
return nil, nil, flowErr
return nil, flowErr
}
fmt.Println("\nPlease wait authenticating...")
currentKeyEncKey, err = enteCrypto.DeriveArgonKey(password,
authResp.KeyAttributes.KEKSalt, authResp.KeyAttributes.MemLimit, authResp.KeyAttributes.OpsLimit)
if err != nil {
fmt.Printf("error deriving key encryption key: %v", err)
return nil, nil, err
return nil, err
}
} else {
currentKeyEncKey = keyEncKey
}
encryptedKey := utils.Base64DecodeString(authResp.KeyAttributes.EncryptedKey)
encryptedKeyNonce := utils.Base64DecodeString(authResp.KeyAttributes.KeyDecryptionNonce)
encryptedKey := utils.DecodeBase64(authResp.KeyAttributes.EncryptedKey)
encryptedKeyNonce := utils.DecodeBase64(authResp.KeyAttributes.KeyDecryptionNonce)
key, keyErr := enteCrypto.SecretBoxOpen(encryptedKey, encryptedKeyNonce, currentKeyEncKey)
if keyErr != nil {
if keyEncKey != nil {
fmt.Printf("Failed to get key from keyEncryptionKey %s", keyErr)
return nil, nil, keyErr
return nil, keyErr
} else {
fmt.Printf("Incorrect password, error decrypting master key: %v", keyErr)
continue
}
}
masterKey, keyErr = enteCrypto.SecretBoxOpen(
utils.Base64DecodeString(authResp.KeyAttributes.EncryptedSecretKey),
utils.Base64DecodeString(authResp.KeyAttributes.SecretKeyDecryptionNonce),
secretKey, keyErr = enteCrypto.SecretBoxOpen(
utils.DecodeBase64(authResp.KeyAttributes.EncryptedSecretKey),
utils.DecodeBase64(authResp.KeyAttributes.SecretKeyDecryptionNonce),
key,
)
if keyErr != nil {
fmt.Printf("error decrypting master key: %v", keyErr)
return nil, nil, keyErr
return nil, keyErr
}
token, err = enteCrypto.SealedBoxOpen(
utils.Base64DecodeString(authResp.EncryptedToken),
utils.Base64DecodeString(authResp.KeyAttributes.PublicKey),
masterKey,
tokenKey, err = enteCrypto.SealedBoxOpen(
utils.DecodeBase64(authResp.EncryptedToken),
utils.DecodeBase64(authResp.KeyAttributes.PublicKey),
secretKey,
)
if err != nil {
fmt.Printf("error decrypting token: %v", err)
return nil, nil, err
return nil, err
}
break
}
return masterKey, token, nil
return &accSecretInfo{
MasterKey: masterKey,
SecretKey: secretKey,
Token: tokenKey,
}, nil
}
func (c *ClICtrl) validateTOTP(ctx context.Context, authResp *api.AuthorizationResponse) (*api.AuthorizationResponse, error) {

View file

@ -4,7 +4,7 @@ import (
"encoding/base64"
)
func Base64DecodeString(s string) []byte {
func DecodeBase64(s string) []byte {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
panic(err)
@ -12,6 +12,6 @@ func Base64DecodeString(s string) []byte {
return b
}
func BytesToBase64(b []byte) string {
func EncodeBase64(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}