diff options
author | Michael Muré <batolettre@gmail.com> | 2022-08-18 23:34:05 +0200 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2022-08-18 23:44:06 +0200 |
commit | 5511c230b678a181cc596238bf6669428d1b1902 (patch) | |
tree | 8701efc87732439f993eb4f1d00585fc419b87ab /identity/key.go | |
parent | 5ca686b59751e3c87740b84108c54fc675a074cf (diff) | |
download | git-bug-5511c230b678a181cc596238bf6669428d1b1902.tar.gz |
move {bug,identity} to /entities, move input to /commands
Diffstat (limited to 'identity/key.go')
-rw-r--r-- | identity/key.go | 234 |
1 files changed, 0 insertions, 234 deletions
diff --git a/identity/key.go b/identity/key.go deleted file mode 100644 index 82b9b95c..00000000 --- a/identity/key.go +++ /dev/null @@ -1,234 +0,0 @@ -package identity - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "strings" - "time" - - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/ProtonMail/go-crypto/openpgp/armor" - "github.com/ProtonMail/go-crypto/openpgp/packet" - "github.com/pkg/errors" - - "github.com/MichaelMure/git-bug/repository" -) - -var errNoPrivateKey = fmt.Errorf("no private key") - -type Key struct { - public *packet.PublicKey - private *packet.PrivateKey -} - -// GenerateKey generate a keypair (public+private) -// The type and configuration of the key is determined by the default value in go's OpenPGP. -func GenerateKey() *Key { - entity, err := openpgp.NewEntity("", "", "", &packet.Config{ - // The armored format doesn't include the creation time, which makes the round-trip data not being fully equal. - // We don't care about the creation time so we can set it to the zero value. - Time: func() time.Time { - return time.Time{} - }, - }) - if err != nil { - panic(err) - } - return &Key{ - public: entity.PrimaryKey, - private: entity.PrivateKey, - } -} - -// generatePublicKey generate only a public key (only useful for testing) -// See GenerateKey for the details. -func generatePublicKey() *Key { - k := GenerateKey() - k.private = nil - return k -} - -func (k *Key) Public() *packet.PublicKey { - return k.public -} - -func (k *Key) Private() *packet.PrivateKey { - return k.private -} - -func (k *Key) Validate() error { - if k.public == nil { - return fmt.Errorf("nil public key") - } - if !k.public.CanSign() { - return fmt.Errorf("public key can't sign") - } - - if k.private != nil { - if !k.private.CanSign() { - return fmt.Errorf("private key can't sign") - } - } - - return nil -} - -func (k *Key) Clone() *Key { - clone := &Key{} - - pub := *k.public - clone.public = &pub - - if k.private != nil { - priv := *k.private - clone.private = &priv - } - - return clone -} - -func (k *Key) MarshalJSON() ([]byte, error) { - // Serialize only the public key, in the armored format. - var buf bytes.Buffer - w, err := armor.Encode(&buf, openpgp.PublicKeyType, nil) - if err != nil { - return nil, err - } - - err = k.public.Serialize(w) - if err != nil { - return nil, err - } - err = w.Close() - if err != nil { - return nil, err - } - return json.Marshal(buf.String()) -} - -func (k *Key) UnmarshalJSON(data []byte) error { - // De-serialize only the public key, in the armored format. - var armored string - err := json.Unmarshal(data, &armored) - if err != nil { - return err - } - - block, err := armor.Decode(strings.NewReader(armored)) - if err == io.EOF { - return fmt.Errorf("no armored data found") - } - if err != nil { - return err - } - - if block.Type != openpgp.PublicKeyType { - return fmt.Errorf("invalid key type") - } - - p, err := packet.Read(block.Body) - if err != nil { - return errors.Wrap(err, "failed to read public key packet") - } - - public, ok := p.(*packet.PublicKey) - if !ok { - return errors.New("got no packet.publicKey") - } - - // The armored format doesn't include the creation time, which makes the round-trip data not being fully equal. - // We don't care about the creation time so we can set it to the zero value. - public.CreationTime = time.Time{} - - k.public = public - return nil -} - -func (k *Key) loadPrivate(repo repository.RepoKeyring) error { - item, err := repo.Keyring().Get(k.public.KeyIdString()) - if err == repository.ErrKeyringKeyNotFound { - return errNoPrivateKey - } - if err != nil { - return err - } - - block, err := armor.Decode(bytes.NewReader(item.Data)) - if err == io.EOF { - return fmt.Errorf("no armored data found") - } - if err != nil { - return err - } - - if block.Type != openpgp.PrivateKeyType { - return fmt.Errorf("invalid key type") - } - - p, err := packet.Read(block.Body) - if err != nil { - return errors.Wrap(err, "failed to read private key packet") - } - - private, ok := p.(*packet.PrivateKey) - if !ok { - return errors.New("got no packet.privateKey") - } - - // The armored format doesn't include the creation time, which makes the round-trip data not being fully equal. - // We don't care about the creation time so we can set it to the zero value. - private.CreationTime = time.Time{} - - k.private = private - return nil -} - -// ensurePrivateKey attempt to load the corresponding private key if it is not loaded already. -// If no private key is found, returns errNoPrivateKey -func (k *Key) ensurePrivateKey(repo repository.RepoKeyring) error { - if k.private != nil { - return nil - } - - return k.loadPrivate(repo) -} - -func (k *Key) storePrivate(repo repository.RepoKeyring) error { - var buf bytes.Buffer - w, err := armor.Encode(&buf, openpgp.PrivateKeyType, nil) - if err != nil { - return err - } - err = k.private.Serialize(w) - if err != nil { - return err - } - err = w.Close() - if err != nil { - return err - } - - return repo.Keyring().Set(repository.Item{ - Key: k.public.KeyIdString(), - Data: buf.Bytes(), - }) -} - -func (k *Key) PGPEntity() *openpgp.Entity { - uid := packet.NewUserId("", "", "") - return &openpgp.Entity{ - PrimaryKey: k.public, - PrivateKey: k.private, - Identities: map[string]*openpgp.Identity{ - uid.Id: { - Name: uid.Id, - UserId: uid, - SelfSignature: &packet.Signature{ - IsPrimaryId: func() *bool { b := true; return &b }(), - }, - }, - }, - } -} |