ente/pkg/sign_in.go

161 lines
4.7 KiB
Go
Raw Normal View History

2023-09-14 04:20:32 +00:00
package pkg
import (
2023-09-23 10:45:10 +00:00
"cli-go/internal"
2023-09-14 04:20:32 +00:00
"cli-go/internal/api"
2023-09-27 02:37:42 +00:00
eCrypto "cli-go/internal/crypto"
2023-09-23 10:45:10 +00:00
"cli-go/pkg/model"
2023-09-23 04:05:37 +00:00
"cli-go/utils/encoding"
2023-09-14 04:20:32 +00:00
"context"
"fmt"
"log"
"github.com/kong/go-srp"
)
2023-09-27 05:32:36 +00:00
func (c *ClICtrl) signInViaPassword(ctx context.Context, srpAttr *api.SRPAttributes) (*api.AuthorizationResponse, []byte, error) {
2023-09-14 04:20:32 +00:00
for {
// CLI prompt for password
2023-09-23 10:45:10 +00:00
password, flowErr := internal.GetSensitiveField("Enter password")
2023-09-14 04:20:32 +00:00
if flowErr != nil {
return nil, nil, flowErr
}
fmt.Println("\nPlease wait authenticating...")
2023-09-27 02:37:42 +00:00
keyEncKey, err := eCrypto.DeriveArgonKey(password, srpAttr.KekSalt, srpAttr.MemLimit, srpAttr.OpsLimit)
2023-09-14 04:20:32 +00:00
if err != nil {
fmt.Printf("error deriving key encryption key: %v", err)
return nil, nil, err
}
2023-09-27 02:37:42 +00:00
loginKey := eCrypto.DeriveLoginKey(keyEncKey)
2023-09-14 04:20:32 +00:00
srpParams := srp.GetParams(4096)
identify := []byte(srpAttr.SRPUserID.String())
2023-09-23 04:05:37 +00:00
salt := encoding.DecodeBase64(srpAttr.SRPSalt)
2023-09-14 04:20:32 +00:00
clientSecret := srp.GenKey()
srpClient := srp.NewClient(srpParams, salt, identify, loginKey, clientSecret)
clientA := srpClient.ComputeA()
2023-09-23 04:05:37 +00:00
session, err := c.Client.CreateSRPSession(ctx, srpAttr.SRPUserID, encoding.EncodeBase64(clientA))
2023-09-14 04:20:32 +00:00
if err != nil {
return nil, nil, err
}
serverB := session.SRPB
2023-09-23 04:05:37 +00:00
srpClient.SetB(encoding.DecodeBase64(serverB))
2023-09-14 04:20:32 +00:00
clientM := srpClient.ComputeM1()
2023-09-23 04:05:37 +00:00
authResp, err := c.Client.VerifySRPSession(ctx, srpAttr.SRPUserID, session.SessionID, encoding.EncodeBase64(clientM))
2023-09-14 04:20:32 +00:00
if err != nil {
log.Printf("failed to verify %v", err)
continue
}
return authResp, keyEncKey, nil
}
2023-09-15 10:47:38 +00:00
}
2023-09-14 04:20:32 +00:00
// Parameters:
// - keyEncKey: key encryption key is derived from user's password. During SRP based login, this key is already derived.
// So, we can pass it to avoid asking for password again.
2023-09-22 16:15:01 +00:00
func (c *ClICtrl) decryptAccSecretInfo(
_ context.Context,
authResp *api.AuthorizationResponse,
keyEncKey []byte,
2023-09-23 10:45:10 +00:00
) (*model.AccSecretInfo, error) {
var currentKeyEncKey []byte
2023-09-22 12:18:14 +00:00
var err error
var masterKey, secretKey, tokenKey []byte
2023-09-23 04:10:54 +00:00
var publicKey = encoding.DecodeBase64(authResp.KeyAttributes.PublicKey)
for {
if keyEncKey == nil {
// CLI prompt for password
2023-09-23 10:45:10 +00:00
password, flowErr := internal.GetSensitiveField("Enter password")
if flowErr != nil {
2023-09-22 12:18:14 +00:00
return nil, flowErr
}
fmt.Println("\nPlease wait authenticating...")
2023-09-27 02:37:42 +00:00
currentKeyEncKey, err = eCrypto.DeriveArgonKey(password,
authResp.KeyAttributes.KEKSalt, authResp.KeyAttributes.MemLimit, authResp.KeyAttributes.OpsLimit)
if err != nil {
fmt.Printf("error deriving key encryption key: %v", err)
2023-09-22 12:18:14 +00:00
return nil, err
}
} else {
currentKeyEncKey = keyEncKey
}
2023-09-23 04:05:37 +00:00
encryptedKey := encoding.DecodeBase64(authResp.KeyAttributes.EncryptedKey)
encryptedKeyNonce := encoding.DecodeBase64(authResp.KeyAttributes.KeyDecryptionNonce)
2023-09-27 02:37:42 +00:00
masterKey, err = eCrypto.SecretBoxOpen(encryptedKey, encryptedKeyNonce, currentKeyEncKey)
if err != nil {
if keyEncKey != nil {
fmt.Printf("Failed to get key from keyEncryptionKey %s", err)
return nil, err
} else {
fmt.Printf("Incorrect password, error decrypting master key: %v", err)
continue
}
}
2023-09-27 02:37:42 +00:00
secretKey, err = eCrypto.SecretBoxOpen(
2023-09-23 04:05:37 +00:00
encoding.DecodeBase64(authResp.KeyAttributes.EncryptedSecretKey),
encoding.DecodeBase64(authResp.KeyAttributes.SecretKeyDecryptionNonce),
masterKey,
)
if err != nil {
fmt.Printf("error decrypting master key: %v", err)
return nil, err
}
2023-09-27 02:37:42 +00:00
tokenKey, err = eCrypto.SealedBoxOpen(
2023-09-23 04:05:37 +00:00
encoding.DecodeBase64(authResp.EncryptedToken),
2023-09-23 04:10:54 +00:00
publicKey,
2023-09-22 12:18:14 +00:00
secretKey,
)
if err != nil {
fmt.Printf("error decrypting token: %v", err)
2023-09-22 12:18:14 +00:00
return nil, err
}
break
}
2023-09-23 10:45:10 +00:00
return &model.AccSecretInfo{
2023-09-22 12:18:14 +00:00
MasterKey: masterKey,
SecretKey: secretKey,
Token: tokenKey,
2023-09-23 04:10:54 +00:00
PublicKey: publicKey,
2023-09-22 12:18:14 +00:00
}, nil
}
2023-09-15 10:47:38 +00:00
func (c *ClICtrl) validateTOTP(ctx context.Context, authResp *api.AuthorizationResponse) (*api.AuthorizationResponse, error) {
if !authResp.IsMFARequired() {
return authResp, nil
}
for {
// CLI prompt for TOTP
2023-09-23 10:45:10 +00:00
totp, flowErr := internal.GetCode("Enter TOTP", 6)
2023-09-15 10:47:38 +00:00
if flowErr != nil {
return nil, flowErr
}
totpResp, err := c.Client.VerifyTotp(ctx, authResp.TwoFactorSessionID, totp)
if err != nil {
log.Printf("failed to verify %v", err)
continue
}
return totpResp, nil
}
2023-09-14 04:20:32 +00:00
}
2023-09-21 03:16:26 +00:00
func (c *ClICtrl) validateEmail(ctx context.Context, email string) (*api.AuthorizationResponse, error) {
err := c.Client.SendEmailOTP(ctx, email)
if err != nil {
return nil, err
}
for {
// CLI prompt for OTP
2023-09-23 10:45:10 +00:00
ott, flowErr := internal.GetCode("Enter OTP", 6)
2023-09-21 03:16:26 +00:00
if flowErr != nil {
return nil, flowErr
}
authResponse, err := c.Client.VerifyEmail(ctx, email, ott)
if err != nil {
log.Printf("failed to verify %v", err)
continue
}
return authResponse, nil
}
}