Store both masterKey and secretKey
This commit is contained in:
parent
b4f0994a34
commit
652cf53e32
|
@ -54,12 +54,12 @@ func (c *ClICtrl) AddAccount(cxt context.Context) {
|
||||||
if authResponse.EncryptedToken == "" || authResponse.KeyAttributes == nil {
|
if authResponse.EncryptedToken == "" || authResponse.KeyAttributes == nil {
|
||||||
panic("no encrypted token or keyAttributes")
|
panic("no encrypted token or keyAttributes")
|
||||||
}
|
}
|
||||||
masterKey, token, decErr := c.decryptMasterKeyAndToken(cxt, authResponse, keyEncKey)
|
secretInfo, decErr := c.decryptMasterKeyAndToken(cxt, authResponse, keyEncKey)
|
||||||
if decErr != nil {
|
if decErr != nil {
|
||||||
flowErr = decErr
|
flowErr = decErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := c.storeAccount(cxt, email, authResponse.ID, app, masterKey, token)
|
err := c.storeAccount(cxt, email, authResponse.ID, app, secretInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flowErr = err
|
flowErr = err
|
||||||
return
|
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
|
// get password
|
||||||
secret := GetOrCreateClISecret()
|
secret := GetOrCreateClISecret()
|
||||||
err := c.DB.Update(func(tx *bolt.Tx) error {
|
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{
|
accInfo := model.Account{
|
||||||
Email: email,
|
Email: email,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
MasterKey: *model.MakeEncString(string(masterKey), secret),
|
MasterKey: *model.MakeEncString(string(secretInfo.MasterKey), secret),
|
||||||
Token: *model.MakeEncString(string(token), secret),
|
Token: *model.MakeEncString(string(secretInfo.Token), secret),
|
||||||
|
SecretKey: *model.MakeEncString(string(secretInfo.SecretKey), secret),
|
||||||
App: app,
|
App: app,
|
||||||
}
|
}
|
||||||
accInfoBytes, err := json.Marshal(accInfo)
|
accInfoBytes, err := json.Marshal(accInfo)
|
||||||
|
|
|
@ -10,6 +10,7 @@ type Account struct {
|
||||||
UserID int64 `json:"userID" binding:"required"`
|
UserID int64 `json:"userID" binding:"required"`
|
||||||
App api.App `json:"app" binding:"required"`
|
App api.App `json:"app" binding:"required"`
|
||||||
MasterKey EncString `json:"masterKey" binding:"required"`
|
MasterKey EncString `json:"masterKey" binding:"required"`
|
||||||
|
SecretKey EncString `json:"secretKey" binding:"required"`
|
||||||
Token EncString `json:"token" binding:"required"`
|
Token EncString `json:"token" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,15 +17,15 @@ func MakeEncString(plainText string, key []byte) *EncString {
|
||||||
log.Fatalf("failed to encrypt %s", err)
|
log.Fatalf("failed to encrypt %s", err)
|
||||||
}
|
}
|
||||||
return &EncString{
|
return &EncString{
|
||||||
CipherText: utils.BytesToBase64(cipher),
|
CipherText: utils.EncodeBase64(cipher),
|
||||||
Nonce: utils.BytesToBase64(nonce),
|
Nonce: utils.EncodeBase64(nonce),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EncString) MustDecrypt(key []byte) string {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return utils.BytesToBase64(plainBytes)
|
return utils.EncodeBase64(plainBytes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ func (c *ClICtrl) SyncAccount(account model.Account) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
token := account.Token.MustDecrypt(cliSecret)
|
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)
|
c.Client.AddToken(account.AccountKey(), urlEncodedToken)
|
||||||
ctx := c.GetRequestContext(context.Background(), account)
|
ctx := c.GetRequestContext(context.Background(), account)
|
||||||
return c.syncRemoteCollections(ctx, account)
|
return c.syncRemoteCollections(ctx, account)
|
||||||
|
|
|
@ -11,6 +11,12 @@ import (
|
||||||
"github.com/kong/go-srp"
|
"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) {
|
func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *api.SRPAttributes) (*api.AuthorizationResponse, []byte, error) {
|
||||||
for {
|
for {
|
||||||
// CLI prompt for password
|
// CLI prompt for password
|
||||||
|
@ -28,18 +34,18 @@ func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *
|
||||||
|
|
||||||
srpParams := srp.GetParams(4096)
|
srpParams := srp.GetParams(4096)
|
||||||
identify := []byte(srpAttr.SRPUserID.String())
|
identify := []byte(srpAttr.SRPUserID.String())
|
||||||
salt := utils.Base64DecodeString(srpAttr.SRPSalt)
|
salt := utils.DecodeBase64(srpAttr.SRPSalt)
|
||||||
clientSecret := srp.GenKey()
|
clientSecret := srp.GenKey()
|
||||||
srpClient := srp.NewClient(srpParams, salt, identify, loginKey, clientSecret)
|
srpClient := srp.NewClient(srpParams, salt, identify, loginKey, clientSecret)
|
||||||
clientA := srpClient.ComputeA()
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
serverB := session.SRPB
|
serverB := session.SRPB
|
||||||
srpClient.SetB(utils.Base64DecodeString(serverB))
|
srpClient.SetB(utils.DecodeBase64(serverB))
|
||||||
clientM := srpClient.ComputeM1()
|
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 {
|
if err != nil {
|
||||||
log.Printf("failed to verify %v", err)
|
log.Printf("failed to verify %v", err)
|
||||||
continue
|
continue
|
||||||
|
@ -55,60 +61,66 @@ func (c *ClICtrl) decryptMasterKeyAndToken(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
authResp *api.AuthorizationResponse,
|
authResp *api.AuthorizationResponse,
|
||||||
keyEncKey []byte,
|
keyEncKey []byte,
|
||||||
) (masterKey, token []byte, err error) {
|
) (*accSecretInfo, error) {
|
||||||
|
|
||||||
var currentKeyEncKey []byte
|
var currentKeyEncKey []byte
|
||||||
|
var masterKey, secretKey, tokenKey []byte
|
||||||
|
var err error
|
||||||
for {
|
for {
|
||||||
if keyEncKey == nil {
|
if keyEncKey == nil {
|
||||||
// CLI prompt for password
|
// CLI prompt for password
|
||||||
password, flowErr := GetSensitiveField("Enter password")
|
password, flowErr := GetSensitiveField("Enter password")
|
||||||
if flowErr != nil {
|
if flowErr != nil {
|
||||||
return nil, nil, flowErr
|
return nil, flowErr
|
||||||
}
|
}
|
||||||
fmt.Println("\nPlease wait authenticating...")
|
fmt.Println("\nPlease wait authenticating...")
|
||||||
currentKeyEncKey, err = enteCrypto.DeriveArgonKey(password,
|
currentKeyEncKey, err = enteCrypto.DeriveArgonKey(password,
|
||||||
authResp.KeyAttributes.KEKSalt, authResp.KeyAttributes.MemLimit, authResp.KeyAttributes.OpsLimit)
|
authResp.KeyAttributes.KEKSalt, authResp.KeyAttributes.MemLimit, authResp.KeyAttributes.OpsLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error deriving key encryption key: %v", err)
|
fmt.Printf("error deriving key encryption key: %v", err)
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentKeyEncKey = keyEncKey
|
currentKeyEncKey = keyEncKey
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedKey := utils.Base64DecodeString(authResp.KeyAttributes.EncryptedKey)
|
encryptedKey := utils.DecodeBase64(authResp.KeyAttributes.EncryptedKey)
|
||||||
encryptedKeyNonce := utils.Base64DecodeString(authResp.KeyAttributes.KeyDecryptionNonce)
|
encryptedKeyNonce := utils.DecodeBase64(authResp.KeyAttributes.KeyDecryptionNonce)
|
||||||
key, keyErr := enteCrypto.SecretBoxOpen(encryptedKey, encryptedKeyNonce, currentKeyEncKey)
|
key, keyErr := enteCrypto.SecretBoxOpen(encryptedKey, encryptedKeyNonce, currentKeyEncKey)
|
||||||
if keyErr != nil {
|
if keyErr != nil {
|
||||||
if keyEncKey != nil {
|
if keyEncKey != nil {
|
||||||
fmt.Printf("Failed to get key from keyEncryptionKey %s", keyErr)
|
fmt.Printf("Failed to get key from keyEncryptionKey %s", keyErr)
|
||||||
return nil, nil, keyErr
|
return nil, keyErr
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Incorrect password, error decrypting master key: %v", keyErr)
|
fmt.Printf("Incorrect password, error decrypting master key: %v", keyErr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
masterKey, keyErr = enteCrypto.SecretBoxOpen(
|
secretKey, keyErr = enteCrypto.SecretBoxOpen(
|
||||||
utils.Base64DecodeString(authResp.KeyAttributes.EncryptedSecretKey),
|
utils.DecodeBase64(authResp.KeyAttributes.EncryptedSecretKey),
|
||||||
utils.Base64DecodeString(authResp.KeyAttributes.SecretKeyDecryptionNonce),
|
utils.DecodeBase64(authResp.KeyAttributes.SecretKeyDecryptionNonce),
|
||||||
key,
|
key,
|
||||||
)
|
)
|
||||||
if keyErr != nil {
|
if keyErr != nil {
|
||||||
fmt.Printf("error decrypting master key: %v", keyErr)
|
fmt.Printf("error decrypting master key: %v", keyErr)
|
||||||
return nil, nil, keyErr
|
return nil, keyErr
|
||||||
}
|
}
|
||||||
token, err = enteCrypto.SealedBoxOpen(
|
tokenKey, err = enteCrypto.SealedBoxOpen(
|
||||||
utils.Base64DecodeString(authResp.EncryptedToken),
|
utils.DecodeBase64(authResp.EncryptedToken),
|
||||||
utils.Base64DecodeString(authResp.KeyAttributes.PublicKey),
|
utils.DecodeBase64(authResp.KeyAttributes.PublicKey),
|
||||||
masterKey,
|
secretKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error decrypting token: %v", err)
|
fmt.Printf("error decrypting token: %v", err)
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
break
|
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) {
|
func (c *ClICtrl) validateTOTP(ctx context.Context, authResp *api.AuthorizationResponse) (*api.AuthorizationResponse, error) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Base64DecodeString(s string) []byte {
|
func DecodeBase64(s string) []byte {
|
||||||
b, err := base64.StdEncoding.DecodeString(s)
|
b, err := base64.StdEncoding.DecodeString(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -12,6 +12,6 @@ func Base64DecodeString(s string) []byte {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func BytesToBase64(b []byte) string {
|
func EncodeBase64(b []byte) string {
|
||||||
return base64.StdEncoding.EncodeToString(b)
|
return base64.StdEncoding.EncodeToString(b)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue