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
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
=TeGE
-----END PGP MESSAGE-----

12
go.mod
View File

@@ -1,11 +1,12 @@
module forge.redroom.link/yves/meowlib
go 1.23.0
go 1.23.1
toolchain go1.24.2
require (
github.com/ProtonMail/gopenpgp/v2 v2.8.3
github.com/awnumar/memguard v0.23.0
github.com/dgraph-io/badger v1.6.2
github.com/go-redis/redis v6.15.9+incompatible
github.com/google/uuid v1.6.0
@@ -22,6 +23,7 @@ require (
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
github.com/ProtonMail/go-crypto v1.2.0 // indirect
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect
github.com/awnumar/memcall v0.4.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -36,11 +38,11 @@ require (
github.com/onsi/gomega v1.30.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchtv/twirp v8.1.3+incompatible // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/crypto v0.41.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect
google.golang.org/grpc v1.62.0 // indirect

24
go.sum
View File

@@ -10,6 +10,10 @@ github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0k
github.com/ProtonMail/gopenpgp/v2 v2.8.3 h1:1jHlELwCR00qovx2B50DkL/FjYwt/P91RnlsqeOp2Hs=
github.com/ProtonMail/gopenpgp/v2 v2.8.3/go.mod h1:LiuOTbnJit8w9ZzOoLscj0kmdALY7hfoCVh5Qlb0bcg=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/awnumar/memcall v0.4.0 h1:B7hgZYdfH6Ot1Goaz8jGne/7i8xD4taZie/PNSFZ29g=
github.com/awnumar/memcall v0.4.0/go.mod h1:8xOx1YbfyuCg3Fy6TO8DK0kZUua3V42/goA5Ru47E8w=
github.com/awnumar/memguard v0.23.0 h1:sJ3a1/SWlcuKIQ7MV+R9p0Pvo9CWsMbGZvcZQtmc68A=
github.com/awnumar/memguard v0.23.0/go.mod h1:olVofBrsPdITtJ2HgxQKrEYEMyIBAIciVG4wNnZhW9M=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -232,8 +236,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -248,15 +252,15 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -278,8 +282,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -292,8 +296,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=