diff --git a/pkg/promt.go b/internal/promt.go similarity index 98% rename from pkg/promt.go rename to internal/promt.go index 65abb0b09..5a9145333 100644 --- a/pkg/promt.go +++ b/internal/promt.go @@ -1,4 +1,4 @@ -package pkg +package internal import ( "cli-go/internal/api" diff --git a/main.go b/main.go index 391e43f80..c5831e766 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "cli-go/cmd" "cli-go/internal/api" "cli-go/pkg" + "cli-go/pkg/secrets" ) func main() { @@ -17,8 +18,8 @@ func main() { Host: "http://localhost:8080", }), DB: db, - CliKey: pkg.GetOrCreateClISecret(), - KeyHolder: pkg.NewKeyHolder(), + CliKey: secrets.GetOrCreateClISecret(), + KeyHolder: secrets.NewKeyHolder(), } err = ctrl.Init() if err != nil { diff --git a/pkg/account.go b/pkg/account.go index 692a08b70..87e145636 100644 --- a/pkg/account.go +++ b/pkg/account.go @@ -1,6 +1,7 @@ package pkg import ( + "cli-go/internal" "cli-go/internal/api" "cli-go/pkg/model" "cli-go/utils/encoding" @@ -21,9 +22,9 @@ func (c *ClICtrl) AddAccount(cxt context.Context) { log.Fatal(flowErr) } }() - app := GetAppType() + app := internal.GetAppType() cxt = context.WithValue(cxt, "app", string(app)) - email, flowErr := GetUserInput("Enter email address") + email, flowErr := internal.GetUserInput("Enter email address") if flowErr != nil { return } @@ -69,7 +70,7 @@ func (c *ClICtrl) AddAccount(cxt context.Context) { } } -func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, app api.App, secretInfo *accSecretInfo) error { +func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, app api.App, secretInfo *model.AccSecretInfo) error { // get password secret := c.CliKey err := c.DB.Update(func(tx *bolt.Tx) error { diff --git a/pkg/collections.go b/pkg/collections.go new file mode 100644 index 000000000..93886a7ae --- /dev/null +++ b/pkg/collections.go @@ -0,0 +1,57 @@ +package pkg + +import ( + "cli-go/internal/api" + enteCrypto "cli-go/internal/crypto" + "cli-go/pkg/model" + "cli-go/utils/encoding" + "context" + "fmt" + "log" +) + +func (c *ClICtrl) syncRemoteCollections(ctx context.Context, info model.Account) error { + collections, err := c.Client.GetCollections(ctx, 0) + if err != nil { + return fmt.Errorf("failed to get collections: %s", err) + } + for _, collection := range collections { + collectionKey, err := c.getCollectionKey(ctx, collection) + if err != nil { + return err + } + name, nameErr := enteCrypto.SecretBoxOpenBase64(collection.EncryptedName, collection.NameDecryptionNonce, collectionKey) + if nameErr != nil { + log.Fatalf("failed to decrypt collection name: %v", nameErr) + } + if collection.Owner.ID != info.UserID { + fmt.Printf("Shared Album %s\n", string(name)) + continue + } else { + fmt.Printf("Owned Name %s\n", string(name)) + } + } + return nil +} + +func (c *ClICtrl) getCollectionKey(ctx context.Context, collection api.Collection) ([]byte, error) { + accSecretInfo := c.KeyHolder.GetAccountSecretInfo(ctx) + userID := ctx.Value("user_id").(int64) + if collection.Owner.ID == userID { + collKey, err := enteCrypto.SecretBoxOpen( + encoding.DecodeBase64(collection.EncryptedKey), + encoding.DecodeBase64(collection.KeyDecryptionNonce), + accSecretInfo.MasterKey) + if err != nil { + log.Fatalf("failed to decrypt collection key %s", err) + } + return collKey, nil + } else { + collKey, err := enteCrypto.SealedBoxOpen(encoding.DecodeBase64(collection.EncryptedKey), + accSecretInfo.PublicKey, accSecretInfo.SecretKey) + if err != nil { + log.Fatalf("failed to decrypt collection key %s", err) + } + return collKey, nil + } +} diff --git a/pkg/controller.go b/pkg/controller.go index 5d794526e..3d2dd2ed0 100644 --- a/pkg/controller.go +++ b/pkg/controller.go @@ -2,6 +2,7 @@ package pkg import ( "cli-go/internal/api" + "cli-go/pkg/secrets" "fmt" bolt "go.etcd.io/bbolt" ) @@ -11,7 +12,7 @@ type ClICtrl struct { DB *bolt.DB // CliKey is the key used to encrypt/decrypt sensitive data stored in the database CliKey []byte - KeyHolder *KeyHolder + KeyHolder *secrets.KeyHolder } func (c *ClICtrl) Init() error { diff --git a/pkg/model/account.go b/pkg/model/account.go index 8556ec8ab..f721835cb 100644 --- a/pkg/model/account.go +++ b/pkg/model/account.go @@ -23,3 +23,10 @@ func (a *Account) AccountKey() string { func (a *Account) DataBucket() string { return fmt.Sprintf("%s-%d-data", a.App, a.UserID) } + +type AccSecretInfo struct { + MasterKey []byte + SecretKey []byte + Token []byte + PublicKey []byte +} diff --git a/pkg/remote_sync.go b/pkg/remote_sync.go index 590155f61..9187fb55d 100644 --- a/pkg/remote_sync.go +++ b/pkg/remote_sync.go @@ -1,10 +1,7 @@ package pkg import ( - "cli-go/internal/api" - enteCrypto "cli-go/internal/crypto" "cli-go/pkg/model" - "cli-go/utils/encoding" "context" "encoding/base64" "fmt" @@ -51,50 +48,3 @@ func createDataBuckets(db *bolt.DB, account model.Account) error { return nil }) } - -func (c *ClICtrl) syncRemoteCollections(ctx context.Context, info model.Account) error { - collections, err := c.Client.GetCollections(ctx, 0) - if err != nil { - return fmt.Errorf("failed to get collections: %s", err) - } - for _, collection := range collections { - - collectionKey, err := c.getCollectionKey(ctx, collection) - if err != nil { - return err - } - name, nameErr := enteCrypto.SecretBoxOpenBase64(collection.EncryptedName, collection.NameDecryptionNonce, collectionKey) - if nameErr != nil { - log.Fatalf("failed to decrypt collection name: %v", nameErr) - } - if collection.Owner.ID != info.UserID { - fmt.Printf("Shared Album %s\n", string(name)) - continue - } else { - fmt.Printf("Owned Name %s\n", string(name)) - } - } - return nil -} - -func (c *ClICtrl) getCollectionKey(ctx context.Context, collection api.Collection) ([]byte, error) { - accSecretInfo := c.KeyHolder.GetAccountSecretInfo(ctx) - userID := ctx.Value("user_id").(int64) - if collection.Owner.ID == userID { - collKey, err := enteCrypto.SecretBoxOpen( - encoding.DecodeBase64(collection.EncryptedKey), - encoding.DecodeBase64(collection.KeyDecryptionNonce), - accSecretInfo.MasterKey) - if err != nil { - log.Fatalf("failed to decrypt collection key %s", err) - } - return collKey, nil - } else { - collKey, err := enteCrypto.SealedBoxOpen(encoding.DecodeBase64(collection.EncryptedKey), - accSecretInfo.PublicKey, accSecretInfo.SecretKey) - if err != nil { - log.Fatalf("failed to decrypt collection key %s", err) - } - return collKey, nil - } -} diff --git a/pkg/key_holder.go b/pkg/secrets/key_holder.go similarity index 69% rename from pkg/key_holder.go rename to pkg/secrets/key_holder.go index f3e266499..198d6a2e4 100644 --- a/pkg/key_holder.go +++ b/pkg/secrets/key_holder.go @@ -1,4 +1,4 @@ -package pkg +package secrets import ( "cli-go/pkg/model" @@ -7,22 +7,22 @@ import ( ) type KeyHolder struct { - AccountSecrets map[string]*accSecretInfo + AccountSecrets map[string]*model.AccSecretInfo CollectionKeys map[string][]byte } func NewKeyHolder() *KeyHolder { return &KeyHolder{ - AccountSecrets: make(map[string]*accSecretInfo), + AccountSecrets: make(map[string]*model.AccSecretInfo), CollectionKeys: make(map[string][]byte), } } -func (k *KeyHolder) LoadSecrets(account model.Account, cliKey []byte) (*accSecretInfo, error) { +func (k *KeyHolder) LoadSecrets(account model.Account, cliKey []byte) (*model.AccSecretInfo, error) { tokenKey := account.Token.MustDecrypt(cliKey) masterKey := account.MasterKey.MustDecrypt(cliKey) secretKey := account.SecretKey.MustDecrypt(cliKey) - k.AccountSecrets[account.AccountKey()] = &accSecretInfo{ + k.AccountSecrets[account.AccountKey()] = &model.AccSecretInfo{ Token: tokenKey, MasterKey: masterKey, SecretKey: secretKey, @@ -31,7 +31,7 @@ func (k *KeyHolder) LoadSecrets(account model.Account, cliKey []byte) (*accSecre return k.AccountSecrets[account.AccountKey()], nil } -func (k *KeyHolder) GetAccountSecretInfo(ctx context.Context) *accSecretInfo { +func (k *KeyHolder) GetAccountSecretInfo(ctx context.Context) *model.AccSecretInfo { accountKey := ctx.Value("account_id").(string) return k.AccountSecrets[accountKey] } diff --git a/pkg/secret.go b/pkg/secrets/secret.go similarity index 97% rename from pkg/secret.go rename to pkg/secrets/secret.go index 3d440863d..3c67bc7b0 100644 --- a/pkg/secret.go +++ b/pkg/secrets/secret.go @@ -1,4 +1,4 @@ -package pkg +package secrets import ( "crypto/rand" diff --git a/pkg/sign_in.go b/pkg/sign_in.go index 44abdbde4..f1e0b970f 100644 --- a/pkg/sign_in.go +++ b/pkg/sign_in.go @@ -1,8 +1,10 @@ package pkg import ( + "cli-go/internal" "cli-go/internal/api" enteCrypto "cli-go/internal/crypto" + "cli-go/pkg/model" "cli-go/utils/encoding" "context" "fmt" @@ -11,17 +13,10 @@ import ( "github.com/kong/go-srp" ) -type accSecretInfo struct { - MasterKey []byte - SecretKey []byte - Token []byte - PublicKey []byte -} - func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *api.SRPAttributes) (*api.AuthorizationResponse, []byte, error) { for { // CLI prompt for password - password, flowErr := GetSensitiveField("Enter password") + password, flowErr := internal.GetSensitiveField("Enter password") if flowErr != nil { return nil, nil, flowErr } @@ -62,7 +57,7 @@ func (c *ClICtrl) decryptAccSecretInfo( _ context.Context, authResp *api.AuthorizationResponse, keyEncKey []byte, -) (*accSecretInfo, error) { +) (*model.AccSecretInfo, error) { var currentKeyEncKey []byte var err error var masterKey, secretKey, tokenKey []byte @@ -70,7 +65,7 @@ func (c *ClICtrl) decryptAccSecretInfo( for { if keyEncKey == nil { // CLI prompt for password - password, flowErr := GetSensitiveField("Enter password") + password, flowErr := internal.GetSensitiveField("Enter password") if flowErr != nil { return nil, flowErr } @@ -117,7 +112,7 @@ func (c *ClICtrl) decryptAccSecretInfo( } break } - return &accSecretInfo{ + return &model.AccSecretInfo{ MasterKey: masterKey, SecretKey: secretKey, Token: tokenKey, @@ -131,7 +126,7 @@ func (c *ClICtrl) validateTOTP(ctx context.Context, authResp *api.AuthorizationR } for { // CLI prompt for TOTP - totp, flowErr := GetCode("Enter TOTP", 6) + totp, flowErr := internal.GetCode("Enter TOTP", 6) if flowErr != nil { return nil, flowErr } @@ -151,7 +146,7 @@ func (c *ClICtrl) validateEmail(ctx context.Context, email string) (*api.Authori } for { // CLI prompt for OTP - ott, flowErr := GetCode("Enter OTP", 6) + ott, flowErr := internal.GetCode("Enter OTP", 6) if flowErr != nil { return nil, flowErr }