Main password encrypted in memory

This commit is contained in:
ycc
2026-02-02 18:15:57 +01:00
parent bb56b8dd9c
commit 7cf212fc76
13 changed files with 145 additions and 110 deletions

View File

@@ -2,8 +2,11 @@ package client
import (
"encoding/json"
"errors"
"os"
"sync"
"github.com/awnumar/memguard"
)
type Config struct {
@@ -47,7 +50,7 @@ type Config struct {
DbSuffix string `json:"db_suffix,omitempty"`
// Inner
memoryPassword string
memoryPassword *memguard.LockedBuffer
additionalPasswords []string
me *Identity
}
@@ -95,12 +98,19 @@ func (c *Config) Save(filename string) error {
return nil
}
func (c *Config) SetMemPass(pass string) {
c.memoryPassword = pass
func (c *Config) SetMemPass(pass string) error {
if c.memoryPassword != nil {
c.memoryPassword.Destroy()
}
c.memoryPassword = memguard.NewBufferFromBytes([]byte(pass))
return nil
}
func (c *Config) GetMemPass() string {
return c.memoryPassword
func (c *Config) GetMemPass() (string, error) {
if c.memoryPassword == nil {
return "", errors.New("password not set")
}
return string(c.memoryPassword.Bytes()), nil
}
func (c *Config) GetIdentity() *Identity {
@@ -116,5 +126,9 @@ func (c *Config) SaveIdentity() error {
}
func (c *Config) Clean() {
if c.memoryPassword != nil {
c.memoryPassword.Destroy()
c.memoryPassword = nil
}
c.additionalPasswords = []string{}
}

View File

@@ -6,7 +6,10 @@ import (
func TestConfigSave(t *testing.T) {
c := GetConfig()
c.memoryPassword = "hideme"
err := c.SetMemPass("hideme")
if err != nil {
t.Fatalf("Failed to set password: %v", err)
}
c.IdentityFile = "test.id"
c.Chunksize = 10000000
c.SavePassword = true

View File

@@ -216,7 +216,10 @@ func (id *Identity) FinalizeInvitation(ReceivedContact *meowlib.ContactCard) err
// LoadIdentity loads an identity from an encrypted file
func LoadIdentity(filename string, password string) (*Identity, error) {
var id Identity
GetConfig().memoryPassword = password
err := GetConfig().SetMemPass(password)
if err != nil {
return nil, err
}
GetConfig().IdentityFile = filename
indata, err := os.ReadFile(filename)
if err != nil {
@@ -242,7 +245,11 @@ func (id *Identity) Save() error {
return errors.New("identity filename empty")
}
b, _ := json.Marshal(id)
armor, err := helper.EncryptMessageWithPassword([]byte(GetConfig().memoryPassword), string(b))
password, err := GetConfig().GetMemPass()
if err != nil {
return err
}
armor, err := helper.EncryptMessageWithPassword([]byte(password), string(b))
if err != nil {
return err
}

View File

@@ -22,7 +22,10 @@ func exists(filename string) bool {
func createId(t *testing.T) *Identity {
config := GetConfig()
config.IdentityFile = "test.id"
config.memoryPassword = "generalPassword"
err := config.SetMemPass("generalPassword")
if err != nil {
t.Fatalf("Failed to set password: %v", err)
}
// ! Extension to quickly open db : Debug only !
config.DbSuffix = ".sqlite"
id, err := CreateIdentity("myname")
@@ -123,7 +126,10 @@ func TestGetRequestJobs(t *testing.T) {
id.MessageServers = ServerStorage{
DbFile: "test.db",
}
GetConfig().SetMemPass("test")
err := GetConfig().SetMemPass("test")
if err != nil {
t.Fatalf("Failed to set password: %v", err)
}
GetConfig().SetIdentity(id)
for i := 1; i < 10; i++ {
// initialize a Server with name "server+i"

View File

@@ -12,17 +12,21 @@ import (
func TestStoreMessage(t *testing.T) {
id := createId(t)
password, err := GetConfig().GetMemPass()
if err != nil {
log.Fatal(err)
}
var um meowlib.UserMessage
um.Data = []byte("blabla")
peers, err := id.Peers.GetPeers()
if err != nil {
log.Fatal(err)
}
err = StoreMessage(peers[0], &um, []string{}, GetConfig().memoryPassword)
err = StoreMessage(peers[0], &um, []string{}, password)
if err != nil {
log.Fatal(err)
}
messages, err := GetMessagesHistory(peers[0], 0, 0, 10, GetConfig().memoryPassword)
messages, err := GetMessagesHistory(peers[0], 0, 0, 10, password)
if err != nil {
log.Fatal(err)
}
@@ -46,9 +50,13 @@ func TestStoreMessage(t *testing.T) {
func TestManyStoreMessage(t *testing.T) {
id := createId(t)
password, err := GetConfig().GetMemPass()
if err != nil {
log.Fatal(err)
}
peers, err := id.Peers.GetPeers()
// test with zero messages
messages, err := GetMessagesHistory(peers[0], 0, 0, 10, GetConfig().memoryPassword)
messages, err := GetMessagesHistory(peers[0], 0, 0, 10, password)
if err != nil {
log.Fatal(err)
}
@@ -56,12 +64,12 @@ func TestManyStoreMessage(t *testing.T) {
for i := 1; i < 100; i++ {
var um meowlib.UserMessage
um.Data = []byte(randomLenString(20, 200))
err := StoreMessage(peers[0], &um, []string{}, GetConfig().memoryPassword)
err := StoreMessage(peers[0], &um, []string{}, password)
if err != nil {
log.Fatal(err)
}
}
messages, err = GetMessagesHistory(peers[0], 0, 0, 10, GetConfig().memoryPassword)
messages, err = GetMessagesHistory(peers[0], 0, 0, 10, password)
if err != nil {
log.Fatal(err)
}

View File

@@ -288,19 +288,27 @@ func (p *Peer) SetDbPassword(password string) {
p.dbPassword = password
}
func (p *Peer) GetDbPassword() string {
func (p *Peer) GetDbPassword() (string, error) {
if p.dbPassword == "" {
return GetConfig().memoryPassword
return GetConfig().GetMemPass()
}
return p.dbPassword
return p.dbPassword, nil
}
func (p *Peer) StoreMessage(msg *meowlib.UserMessage, filenames []string) error {
return StoreMessage(p, msg, filenames, p.GetDbPassword())
password, err := p.GetDbPassword()
if err != nil {
return err
}
return StoreMessage(p, msg, filenames, password)
}
func (p *Peer) GetFilePreview(filename string) ([]byte, error) {
return FilePreview(filename, p.GetDbPassword())
password, err := p.GetDbPassword()
if err != nil {
return nil, err
}
return FilePreview(filename, password)
}
func (p *Peer) UpdateMessage(msg InternalUserMessage) error {
@@ -308,12 +316,20 @@ func (p *Peer) UpdateMessage(msg InternalUserMessage) error {
}
func (p *Peer) LoadMessagesHistory(alreadyLoadedCount int, oldestMessageId int, qty int) ([]InternalUserMessage, error) {
return GetMessagesHistory(p, alreadyLoadedCount, oldestMessageId, qty, p.GetDbPassword())
password, err := p.GetDbPassword()
if err != nil {
return nil, err
}
return GetMessagesHistory(p, alreadyLoadedCount, oldestMessageId, qty, password)
}
func (p *Peer) LoadNewMessages(lastMessageId int) ([]*InternalUserMessage, error) {
return GetNewMessages(p, lastMessageId, p.GetDbPassword())
password, err := p.GetDbPassword()
if err != nil {
return nil, err
}
return GetNewMessages(p, lastMessageId, password)
}
func (p *Peer) LoadMessage(uid string) (*InternalUserMessage, error) {

View File

@@ -52,7 +52,10 @@ func (ps *PeerStorage) StorePeer(peer *Peer) error {
if err != nil {
return err
}
password := GetConfig().memoryPassword
password, err := GetConfig().GetMemPass()
if err != nil {
return err
}
if peer.dbPassword != "" {
password = peer.dbPassword
}

View File

@@ -8,7 +8,10 @@ import (
func TestStorePeer(t *testing.T) {
id := createId(t)
GetConfig().SetMemPass("test")
err := GetConfig().SetMemPass("test")
if err != nil {
t.Fatalf("Failed to set password: %v", err)
}
GetConfig().SetIdentity(id)
ps := &PeerStorage{
DbFile: "peerdb.test",
@@ -24,13 +27,17 @@ func TestStorePeer(t *testing.T) {
ContactPublicKey: "testContactPublicKey",
}
err := ps.StorePeer(peer)
err = ps.StorePeer(peer)
if err != nil {
t.Errorf("Failed to store peer: %v", err)
}
// load the peer from the database
peers, err := ps.LoadPeers(GetConfig().GetMemPass())
password, err := GetConfig().GetMemPass()
if err != nil {
t.Fatalf("Failed to get password: %v", err)
}
peers, err := ps.LoadPeers(password)
if err != nil {
t.Errorf("Failed to load peers: %v", err)
}

View File

@@ -42,7 +42,11 @@ func (ss *ServerStorage) StoreServer(sc *Server) error {
if err != nil {
return err
}
data, err := meowlib.SymEncrypt(GetConfig().memoryPassword, jsonsrv)
password, err := GetConfig().GetMemPass()
if err != nil {
return err
}
data, err := meowlib.SymEncrypt(password, jsonsrv)
if err != nil {
return err
}
@@ -96,6 +100,10 @@ func (ss *ServerStorage) LoadServer(uid string) (*Server, error) {
return nil, err
}
defer ss.close()
password, err := GetConfig().GetMemPass()
if err != nil {
return nil, err
}
shakey := sha256.Sum256([]byte(uid))
key := shakey[:]
err = ss.db.View(func(txn *badger.Txn) error {
@@ -104,7 +112,7 @@ func (ss *ServerStorage) LoadServer(uid string) (*Server, error) {
return err
}
return item.Value(func(val []byte) error {
jsonsrv, err := meowlib.SymDecrypt(GetConfig().memoryPassword, val)
jsonsrv, err := meowlib.SymDecrypt(password, val)
if err != nil {
return err
}
@@ -136,6 +144,10 @@ func (ss *ServerStorage) LoadAllServers() ([]*Server, error) {
return nil, err
}
defer ss.close()
password, err := GetConfig().GetMemPass()
if err != nil {
return nil, err
}
err = ss.db.View(func(txn *badger.Txn) error {
opts := badger.DefaultIteratorOptions
opts.PrefetchSize = 10
@@ -145,7 +157,7 @@ func (ss *ServerStorage) LoadAllServers() ([]*Server, error) {
item := it.Item()
var sc Server
err := item.Value(func(val []byte) error {
jsonsrv, err := meowlib.SymDecrypt(GetConfig().memoryPassword, val)
jsonsrv, err := meowlib.SymDecrypt(password, val)
if err != nil {
return err
}
@@ -169,6 +181,10 @@ func (ss *ServerStorage) LoadAllServerCards() ([]*meowlib.ServerCard, error) {
return nil, err
}
defer ss.close()
password, err := GetConfig().GetMemPass()
if err != nil {
return nil, err
}
err = ss.db.View(func(txn *badger.Txn) error {
opts := badger.DefaultIteratorOptions
opts.PrefetchSize = 10
@@ -178,7 +194,7 @@ func (ss *ServerStorage) LoadAllServerCards() ([]*meowlib.ServerCard, error) {
item := it.Item()
var sc Server
err := item.Value(func(val []byte) error {
jsonsrv, err := meowlib.SymDecrypt(GetConfig().memoryPassword, val)
jsonsrv, err := meowlib.SymDecrypt(password, val)
if err != nil {
return err
}
@@ -202,6 +218,10 @@ func (ss *ServerStorage) LoadServersFromUids(uids []string) ([]*Server, error) {
return nil, err
}
defer ss.close()
password, err := GetConfig().GetMemPass()
if err != nil {
return nil, err
}
err = ss.db.View(func(txn *badger.Txn) error {
for _, uid := range uids {
shakey := sha256.Sum256([]byte(uid))
@@ -212,7 +232,7 @@ func (ss *ServerStorage) LoadServersFromUids(uids []string) ([]*Server, error) {
}
var sc Server
err = item.Value(func(val []byte) error {
jsonsrv, err := meowlib.SymDecrypt(GetConfig().memoryPassword, val)
jsonsrv, err := meowlib.SymDecrypt(password, val)
if err != nil {
return err
}
@@ -236,6 +256,10 @@ func (ss *ServerStorage) LoadServerCardsFromUids(uids []string) ([]*meowlib.Serv
return nil, err
}
defer ss.close()
password, err := GetConfig().GetMemPass()
if err != nil {
return nil, err
}
err = ss.db.View(func(txn *badger.Txn) error {
for _, uid := range uids {
shakey := sha256.Sum256([]byte(uid))
@@ -246,7 +270,7 @@ func (ss *ServerStorage) LoadServerCardsFromUids(uids []string) ([]*meowlib.Serv
}
var sc Server
err = item.Value(func(val []byte) error {
jsonsrv, err := meowlib.SymDecrypt(GetConfig().memoryPassword, val)
jsonsrv, err := meowlib.SymDecrypt(password, val)
if err != nil {
return err
}

View File

@@ -58,7 +58,10 @@ func TestStoreServer(t *testing.T) {
func TestLoadServersFromUids(t *testing.T) {
createId(t)
GetConfig().SetMemPass("test")
err := GetConfig().SetMemPass("test")
if err != nil {
t.Fatalf("Failed to set password: %v", err)
}
ss := ServerStorage{DbFile: "test.db"}
k, err := meowlib.NewKeyPair()
if err != nil {

View File

@@ -1,62 +0,0 @@
-----BEGIN PGP MESSAGE-----
Comment: https://gopenpgp.org
Version: GopenPGP 2.8.3
wy4ECQMInmXlByyt4CPgpCNwV3lL23ekoUhzNzbjapKhWeUNPI9THbw8u0ZgHweH
0usBMtHasKEhHil4cJAyTfXcn9MPjUN0b0xZQvjWSSmcvEnTWqHthSAmMZOa+tsL
FuqRpi31V4WMfK17xSRskI2otDnZAQTF2ZypmyLZbs1WfKRcbVa16cLSDHvW6ar2
4Gzh14Gmnms/Bgf+CwfvX7aa7FGwua+dKQsNnpq6kXvk71UpZszxOfG+1h7o3EXN
F203djIIgiXbYA8bskMC2nyDrgiyKwAiDQIhDE7hUfH3ym7hp8b7K2nDLki63edO
+sClYnbvGQypq/uN+G/12BSQJEFY/pfBqpXgecnpUbr7gamx35S0r93385sNTtUU
zQGIkzNx7akyBYBHnbs5yYQi9/fJSzpfEYqoNvHpxZBeYVLvxvAuHT0aZtuihGrK
1torjlQAk+aLJa/SGoFUhkrrHyr+J3hjBZieN5f8un5EWVA6KrHkg9WCHXG0d5ko
1BhN8sCaEZN4p0S/Hn0buk7qpdkcxLVpNIjOqUUcu++oIZRRff5FSHGYMgaX5Pjg
ENGFv9fUbimx/csgKTANlh0M1jl4+ZiXQQ7DarmN2amIYFwlxEq0n9o42wmdTGM9
63IHrldcwZQ/Md9ZEXQyhkaZ5g2kdJfn7xqkCX0aVJB4HdgJp0nPFBRoT0quZjRj
9jE1i9RQUN6pa5OOkMD6zmf9myDBWzmkYUXuU+8UaX8yleB5Jh0/kP0F4pRqkYwW
SkLcErmsM1zcvDgi2JnSeydOqNRZs4iM3sou+WIut1CTBuV/qc0X1FRz1f5R7Zg1
ZxT8U0Ot5h0BMSV258Hvlvu8dCx0onYt5X2XgjNNbhZ3vTIRgHcQGLhHHYmXIe9F
OexbaL+AhDxlTqb+2DNhmgm/DIl0IFQmUHr1V4gedGxF1gyOYAqVmuxezGTEoFiw
ysKTwpm0TbbIUG0/rgrBBvTO2vWOBosmW5t4xP3MvxoZhSVHBBfiWkmoz6kAH8QP
AwCO4i7nwrHL70itE3mjo6nt+9Hcc2ZWZvp+VahIQAQJxVORhiRB/KOOprevv6Xz
8TKBqUrn62n/+/KT5rMMh1wY/7J3kGzzzZpBb527iS8cao7OP4lMBYO7rP2JDhg9
uFOjX+Vgk+Tniw3yX/BsA5JJq10SnfK1YmyK4tRKJu8+hWuExDbcdy8+IjNWDVyA
oQ8PrCP4oKMk2o5IMf+S/gqDUi7MxquIWOgiYO744m0HPORu17o++hHEnv4B4gqh
nE1C20O9N4OOD9VAqHk8PfZUX2aahAIhaQmW+iG9U9sQ7S5OZ4lE6gmLKu1ftLkv
w1fbomoQlCqZOY6FvTnUHhTtP9YEzGsy/BLwedkEMVBpDSJxRgP3wzYHrbrsBrpW
RIcQ0X7lYGfgqC9jGt+qkNIjBPCLzxo2Bs9UGVxz+cHm8Uf60q0HbkOLm9NGWUOC
V51LKyYo12lysDayWL5x5XZLHXN+y3OwbxApw8IMqOP5xzPfMVdWDvvmZUG4cCAr
vmfSg0/QyB+5wEqrU2sbNF/+OKuInTxOL2/hUukKUSlUtshCX8/9vbuvv73f24XG
llyuSS49WrScgzzXroaz8px3bmY1XxTICvySuazzfAA7hUDPtZSLRzr3nCp+ZCgb
xLPD3Dq/YtAfqZa8wmuycQynD4JOOWpnNqzoGHZF1cRfpyK84WVwEUwk99PpeHvX
2D16jtY3jhH3D+wsaPJ4U70oLH1tCzNSdhJHdy65IUz3Goc0iTGHYM+rjkL8R0vA
+06epi4WbuEqjYyp1TslvsZEATaimDsMPROI5VbEk6KZVKoAWCH1T4b1SNCFbPfl
kjmGjBQdKO7MgU9Umwu5q0T8ugZtu+V3F/wOVZX5LpaAO8xrVp4kD180AmJHSd2k
6WrjFsZzOrqfqr5DtpyMoyjUMWIzhG6ZpLrBAXYUq6DFSb17lJXa+YYCHUvBN7Ma
2NWwSJJqf7XS1sYf2g+/D8dBpGwrFFqdRcopAHSW9JfkB8qw397wbaIcaGP5grxb
hgSOLEtdM3tL4Mka+AoHXmU05FH4x77oSPGJ9EfMmoIXEz3QM8CHQvC/K4uJejaw
HwJ9s4+5AYGgFng+lS4PAonSX/bgyTY+nJXEYJAIHaVs1TvF9jKXw8zcUUvt7xRw
4djB1CYnQdzhT4Pf9hBjJXm3sUOHNByODPKh9RNarj33kKBDo6lhx+eRb0Qz2xNQ
oHrwpObmkwBu9+MNfjqj99CSD6WVyPaOuzg7yxaEDILCcN92eVva3FXPacQuIBfE
Pjr69TRIsHNZQ7Pfa0BxQc0e7x8s2fyAovy87YcDSjXCVeQD9Wj3zUPeZCtROUcx
WTkyMAE5uPl8oy8d5kCBLyq8iy3WSOmeFXBtduul4J+//ub9KZ9Nw85wO5mBtTn2
AdXtw1yypZbH6jdAJ0ZZRWE8xCh5f61X8TKgxqt+gLeMOK67Kx/IzlhDxpE+jcpp
TAr/lsuvMeYaDXz4RXIprf4Lf5xZR3UMAiB0MndGVplQPOj2VIxUXYeO+ZvDB8lD
0UJpFdXUhwXXyQe6Km+U0LpfdascX2L3ZG4JZ3FU52xM8fJplVlxKkDKFTUV2Q5y
IIsEFvE8BJO3IDynyXXjfEdo3vjmuOaqXwTSH/t0MIWRtUsFwjHaVkakijBSDWM3
fSjVNr6c2eDvl7OMmHkzkHIzf4DxjBMOpXXTpWjEqycP9hMvl+n49r38SE1zetbR
78iZ9ZrHVuMiICkCywBfR6VFWhv/cDhct+FyD5CEU83QpMGBQWWaxqmTWoNE6eLg
g6MdvKMCzu5R4Eu5YxjjY2SrHKTjUgWdljUi9KPgDDSIg04lfkYb+8uQu8oviwBf
q9T0+51GQhFQcxVmOkhcYkDpdBgLAqPONfwVKkeVFKcyGcjpJXtTyQlTllMBGGNQ
qgyYVxbc/xy4Apq5TGdTIgJ77aUgz7Vspyr1HnSgdrUsPFJ6M5v/tIEIIKiftTyY
WPzmhiGM7CFcDi5tSMX5TuoZBfysAO1GOpdLJT9MOBME4Yx0W8GC8RWVF/Av80CI
svbFwfIqZqOLxulI4z39Gwy+2EPtpx1/GIasMf+r0K+uOpC3tOHUwAHdIHuNlHXJ
NsAf351sqzVkExSvjVQFgYGsOaX/ChjWb8EebHzOfHOVnVFB9P/EXzB/OM6zPeld
dI64A+rrlCC5mXPH9P0k/XQXRmxA19d8xPLJzEA81Xu2QEdzftAbNULXkCxn4hG2
ViRbPgXdso4etJcA0CsTywXUKSdA2N2GhmShKqjulaPdtwCBm02CdIpMpUoUlZFJ
Y4VIMx+RlQUZWAcY+dNEbD6/OGPZjpRMaKjkCFdjHkQ/WTbWjiYGtUvCimdfHhFI
x1vyzFmhB/qW8Np/YjAB9ooRQ+qpjCWocegje2pN4rEOLw500sjJXYeb/DQzYuVa
urIA29XBNsajC7ByJJmhpIcXMCuEwv7DcbbOx1SK9u90CbHUwh8g6oSQ9FcYAm+L
J7mcayjSu4X/A+trX7W/MP5spCELDRJuxuol/jj5f63vTqImCA==
=TeGE
-----END PGP MESSAGE-----