Add export/import methods

This commit is contained in:
Andrea Maria Piana 2021-01-07 12:15:02 +01:00
parent fb6411af24
commit b1a1a223c2
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
4 changed files with 144 additions and 0 deletions

View File

@ -400,6 +400,60 @@ func (b *GethStatusBackend) StartNodeWithAccount(acc multiaccounts.Account, pass
return err return err
} }
func (b *GethStatusBackend) ExportUnencryptedDatabase(acc multiaccounts.Account, password, directory string) error {
b.mu.Lock()
defer b.mu.Unlock()
if b.appDB != nil {
return nil
}
if len(b.rootDataDir) == 0 {
return errors.New("root datadir wasn't provided")
}
// Migrate file path to fix issue https://github.com/status-im/status-go/issues/2027
oldPath := filepath.Join(b.rootDataDir, fmt.Sprintf("app-%x.sql", acc.KeyUID))
newPath := filepath.Join(b.rootDataDir, fmt.Sprintf("%s.db", acc.KeyUID))
_, err := os.Stat(oldPath)
if err == nil {
err := os.Rename(oldPath, newPath)
if err != nil {
return err
}
// rename journals as well, but ignore errors
_ = os.Rename(oldPath+"-shm", newPath+"-shm")
_ = os.Rename(oldPath+"-wal", newPath+"-wal")
}
err = appdatabase.DecryptDatabase(newPath, directory, password)
if err != nil {
b.log.Error("failed to initialize db", "err", err)
return err
}
return nil
}
func (b *GethStatusBackend) ImportUnencryptedDatabase(acc multiaccounts.Account, password, databasePath string) error {
b.mu.Lock()
defer b.mu.Unlock()
if b.appDB != nil {
return nil
}
if len(b.rootDataDir) == 0 {
return errors.New("root datadir wasn't provided")
}
path := filepath.Join(b.rootDataDir, fmt.Sprintf("%s.db", acc.KeyUID))
err := appdatabase.EncryptDatabase(databasePath, path, password)
if err != nil {
b.log.Error("failed to initialize db", "err", err)
return err
}
return nil
}
func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(acc multiaccounts.Account, password string, settings accounts.Settings, nodecfg *params.NodeConfig, subaccs []accounts.Account, keyHex string) error { func (b *GethStatusBackend) SaveAccountAndStartNodeWithKey(acc multiaccounts.Account, password string, settings accounts.Settings, nodecfg *params.NodeConfig, subaccs []accounts.Account, keyHex string) error {
err := b.SaveAccount(acc) err := b.SaveAccount(acc)
if err != nil { if err != nil {

View File

@ -19,3 +19,15 @@ func InitializeDB(path, password string) (*sql.DB, error) {
} }
return db, nil return db, nil
} }
// DecryptDatabase creates an unencrypted copy of the database and copies it
// over to the given directory
func DecryptDatabase(oldPath, newPath, password string) error {
return sqlite.DecryptDB(oldPath, newPath, password)
}
// EncryptDatabase creates an encrypted copy of the database and copies it to the
// user path
func EncryptDatabase(oldPath, newPath, password string) error {
return sqlite.EncryptDB(oldPath, newPath, password)
}

View File

@ -628,3 +628,31 @@ func MultiformatDeserializePublicKey(key, outBase string) string {
return pk return pk
} }
// ExportUnencryptedDatabase exports the database unencrypted to the given path
func ExportUnencryptedDatabase(accountData, password, databasePath string) string {
var account multiaccounts.Account
err := json.Unmarshal([]byte(accountData), &account)
if err != nil {
return makeJSONResponse(err)
}
err = statusBackend.ExportUnencryptedDatabase(account, password, databasePath)
if err != nil {
return makeJSONResponse(err)
}
return makeJSONResponse(nil)
}
// ImportUnencryptedDatabase imports the database unencrypted to the given directory
func ImportUnencryptedDatabase(accountData, password, databasePath string) string {
var account multiaccounts.Account
err := json.Unmarshal([]byte(accountData), &account)
if err != nil {
return makeJSONResponse(err)
}
err = statusBackend.ImportUnencryptedDatabase(account, password, databasePath)
if err != nil {
return makeJSONResponse(err)
}
return makeJSONResponse(nil)
}

View File

@ -4,6 +4,7 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
"os"
_ "github.com/mutecomm/go-sqlcipher" // We require go sqlcipher that overrides default implementation _ "github.com/mutecomm/go-sqlcipher" // We require go sqlcipher that overrides default implementation
) )
@ -18,6 +19,55 @@ const (
WALMode = "wal" WALMode = "wal"
) )
// DecryptDB completely removes the encryption from the db
func DecryptDB(oldPath, newPath, key string) error {
db, err := openDB(oldPath, key)
if err != nil {
return err
}
_, err = db.Exec(`ATTACH DATABASE '` + newPath + `' AS plaintext KEY ''`)
if err != nil {
return err
}
_, err = db.Exec(`SELECT sqlcipher_export('plaintext')`)
if err != nil {
return err
}
_, err = db.Exec(`DETACH DATABASE plaintext`)
return err
}
// EncryptDB takes a plaintext database and adds encryption
func EncryptDB(unencryptedPath, encryptedPath, key string) error {
_ = os.Remove(encryptedPath)
db, err := OpenUnecryptedDB(unencryptedPath)
if err != nil {
return err
}
_, err = db.Exec(`ATTACH DATABASE '` + encryptedPath + `' AS encrypted KEY '` + key + `'`)
if err != nil {
return err
}
_, err = db.Exec(fmt.Sprintf("PRAGMA encrypted.kdf_iter = '%d'", kdfIterationsNumber))
if err != nil {
return err
}
_, err = db.Exec(`SELECT sqlcipher_export('encrypted')`)
if err != nil {
return err
}
_, err = db.Exec(`DETACH DATABASE encrypted`)
return err
}
func openDB(path, key string) (*sql.DB, error) { func openDB(path, key string) (*sql.DB, error) {
db, err := sql.Open("sqlite3", path) db, err := sql.Open("sqlite3", path)
if err != nil { if err != nil {