Skip to content

Commit

Permalink
Reorganise
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim van der Molen committed Jul 29, 2024
1 parent 1eaa71b commit 1c31ed4
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 63 deletions.
32 changes: 16 additions & 16 deletions safestorage/decrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,42 @@ const (
keySize = 16 // AES-128
salt = "saltysalt"

keychainPrefix = "v10"
keychainIterations = 1003
macosPrefix = "v10"
macosIterations = 1003

libsecretPrefixV10 = "v10"
libsecretPrefixV11 = "v11"
libsecretIterations = 1
linuxPrefixV10 = "v10"
linuxPrefixV11 = "v11"
linuxIterations = 1
)

func DecryptWithPassword(ciphertext, password []byte) ([]byte, error) {
switch runtime.GOOS {
case "darwin":
return decryptWithKeychainPassword(ciphertext, password)
return decryptWithMacosPassword(ciphertext, password)
case "linux", "openbsd":
return decryptWithLibsecretPassword(ciphertext, password)
return decryptWithLinuxPassword(ciphertext, password)
default:
return nil, errors.New("not yet supported")
}
}

func decryptWithKeychainPassword(ciphertext, password []byte) ([]byte, error) {
if !bytes.HasPrefix(ciphertext, []byte(keychainPrefix)) {
func decryptWithMacosPassword(ciphertext, password []byte) ([]byte, error) {
if !bytes.HasPrefix(ciphertext, []byte(macosPrefix)) {
return ciphertext, nil
}
ciphertext = bytes.TrimPrefix(ciphertext, []byte(keychainPrefix))
return decryptWithPassword(ciphertext, password, keychainIterations)
ciphertext = bytes.TrimPrefix(ciphertext, []byte(macosPrefix))
return decryptWithPassword(ciphertext, password, macosIterations)
}

func decryptWithLibsecretPassword(ciphertext, password []byte) ([]byte, error) {
if bytes.HasPrefix(ciphertext, []byte(libsecretPrefixV10)) {
func decryptWithLinuxPassword(ciphertext, password []byte) ([]byte, error) {
if bytes.HasPrefix(ciphertext, []byte(linuxPrefixV10)) {
return nil, errors.New("unsupported encryption version prefix")
}
if !bytes.HasPrefix(ciphertext, []byte(libsecretPrefixV11)) {
if !bytes.HasPrefix(ciphertext, []byte(linuxPrefixV11)) {
return ciphertext, nil
}
ciphertext = bytes.TrimPrefix(ciphertext, []byte(libsecretPrefixV11))
return decryptWithPassword(ciphertext, password, libsecretIterations)
ciphertext = bytes.TrimPrefix(ciphertext, []byte(linuxPrefixV11))
return decryptWithPassword(ciphertext, password, linuxIterations)
}

func decryptWithPassword(ciphertext, password []byte, iters int) ([]byte, error) {
Expand Down
73 changes: 26 additions & 47 deletions signal/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,10 @@ type Context struct {
}

func Open(dir string) (*Context, error) {
key, err := databaseKey(dir)
if err != nil {
return nil, err
}
return open(dir, key)
return OpenWithPassword(dir, nil)
}

func OpenWithPassword(dir string, password []byte) (*Context, error) {
key, err := encryptedDatabaseKey(dir, password)
if err != nil {
return nil, err
}
return open(dir, key)
}

func open(dir string, key []byte) (*Context, error) {
dbFile := filepath.Join(dir, DatabaseFile)

// SQLite/SQLCipher doesn't provide a useful error message if the
Expand All @@ -66,6 +54,11 @@ func open(dir string, key []byte) (*Context, error) {
return nil, err
}

key, err := databaseKey(dir, password)
if err != nil {
return nil, err
}

// Format the key as an SQLite blob literal
key = []byte(fmt.Sprintf("x'%s'", string(key)))

Expand Down Expand Up @@ -104,57 +97,43 @@ func (c *Context) Close() {
c.db.Close()
}

type config struct {
Key *string `json:"key"`
EncryptedKey *string `json:"encryptedKey"`
}

func databaseKey(dir string) ([]byte, error) {
config, err := parseConfigFile(dir)
func databaseKey(dir string, password []byte) ([]byte, error) {
configFile := filepath.Join(dir, ConfigFile)
data, err := os.ReadFile(configFile)
if err != nil {
return nil, err
}

if config.Key == nil {
return nil, fmt.Errorf("legacy database key not found")
var config struct {
LegacyKey *string `json:"key"`
ModernKey *string `json:"encryptedKey"`
}
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("cannot parse %s: %w", configFile, err)
}

return []byte(*config.Key), nil
}

func encryptedDatabaseKey(dir string, password []byte) ([]byte, error) {
config, err := parseConfigFile(dir)
if err != nil {
return nil, err
if password == nil && config.LegacyKey != nil {
return []byte(*config.LegacyKey), nil
}

if config.EncryptedKey == nil {
if config.ModernKey == nil {
return nil, fmt.Errorf("encrypted database key not found")
}

encKey, err := hex.DecodeString(*config.EncryptedKey)
key, err := hex.DecodeString(*config.ModernKey)
if err != nil {
return nil, fmt.Errorf("invalid encrypted database key: %w", err)
}

key, err := safestorage.DecryptWithPassword(encKey, password)
if err != nil {
return nil, fmt.Errorf("cannot decrypt database key: %w", err)
var dbKey []byte
if password != nil {
dbKey, err = safestorage.DecryptWithPassword(key, password)
} else {
err = fmt.Errorf("not yet supported")
}

return key, nil
}

func parseConfigFile(dir string) (config, error) {
configFile := filepath.Join(dir, ConfigFile)
data, err := os.ReadFile(configFile)
if err != nil {
return config{}, err
return nil, fmt.Errorf("cannot decrypt database key: %w", err)
}

var config config
if err := json.Unmarshal(data, &config); err != nil {
return config, fmt.Errorf("cannot parse %s: %w", configFile, err)
}
return config, nil
return dbKey, nil
}

0 comments on commit 1c31ed4

Please sign in to comment.