package lib import ( "fmt" "io" "os" "path" "github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/kyoh86/xdg" ) var ( Keyring openpgp.EntityList locked bool ) func InitKeyring() { os.MkdirAll(path.Join(xdg.DataHome(), "aerc"), 0700) lockpath := path.Join(xdg.DataHome(), "aerc", "keyring.lock") lockfile, err := os.OpenFile(lockpath, os.O_CREATE|os.O_EXCL, 0600) if err != nil { // TODO: Consider connecting to main process over IPC socket locked = false } else { locked = true lockfile.Close() } keypath := path.Join(xdg.DataHome(), "aerc", "keyring.asc") keyfile, err := os.Open(keypath) if os.IsNotExist(err) { return } else if err != nil { panic(err) } defer keyfile.Close() Keyring, err = openpgp.ReadKeyRing(keyfile) if err != nil { panic(err) } } func UnlockKeyring() { if !locked { return } lockpath := path.Join(xdg.DataHome(), "aerc", "keyring.lock") os.Remove(lockpath) } func GetEntityByEmail(email string) (e *openpgp.Entity, err error) { for _, entity := range Keyring { ident := entity.PrimaryIdentity() if ident != nil && ident.UserId.Email == email { return entity, nil } } return nil, fmt.Errorf("entity not found in keyring") } func GetSignerEntityByEmail(email string) (e *openpgp.Entity, err error) { for _, key := range Keyring.DecryptionKeys() { if key.Entity == nil { continue } ident := key.Entity.PrimaryIdentity() if ident != nil && ident.UserId.Email == email { return key.Entity, nil } } return nil, fmt.Errorf("entity not found in keyring") } func ImportKeys(r io.Reader) error { keys, err := openpgp.ReadKeyRing(r) if err != nil { return err } Keyring = append(Keyring, keys...) if locked { keypath := path.Join(xdg.DataHome(), "aerc", "keyring.asc") keyfile, err := os.OpenFile(keypath, os.O_CREATE|os.O_APPEND, 0600) if err != nil { return err } defer keyfile.Close() for _, key := range keys { if key.PrivateKey != nil { err = key.SerializePrivate(keyfile, &packet.Config{}) } else { err = key.Serialize(keyfile) } if err != nil { return err } } } return nil }