1package identity
2
3import (
4 "encoding/hex"
5 "fmt"
6 "strings"
7
8 "github.com/pkg/errors"
9 "golang.org/x/crypto/openpgp/armor"
10 "golang.org/x/crypto/openpgp/packet"
11)
12
13type Key struct {
14 // PubKey is the armored PGP public key.
15 ArmoredPublicKey string `json:"pub_key"`
16
17 PublicKey *packet.PublicKey `json:"-"`
18}
19
20func NewKey(armoredPGPKey string) (*Key, error) {
21 publicKey, err := parsePublicKey(armoredPGPKey)
22 if err != nil {
23 return nil, err
24 }
25
26 return &Key{armoredPGPKey, publicKey}, nil
27}
28
29func parsePublicKey(armoredPublicKey string) (*packet.PublicKey, error) {
30 block, err := armor.Decode(strings.NewReader(armoredPublicKey))
31 if err != nil {
32 return nil, errors.Wrap(err, "failed to dearmor public key")
33 }
34
35 reader := packet.NewReader(block.Body)
36 p, err := reader.Next()
37 if err != nil {
38 return nil, errors.Wrap(err, "failed to read public key packet")
39 }
40
41 publicKey, ok := p.(*packet.PublicKey)
42 if !ok {
43 return nil, errors.New("got no packet.PublicKey")
44 }
45
46 return publicKey, nil
47}
48
49// DecodeKeyFingerprint decodes a 40 hex digits long fingerprint into bytes.
50func DecodeKeyFingerprint(keyFingerprint string) ([20]byte, error) {
51 var fingerprint [20]byte
52 fingerprintBytes, err := hex.DecodeString(keyFingerprint)
53 if err != nil {
54 return fingerprint, err
55 }
56 if len(fingerprintBytes) != 20 {
57 return fingerprint, fmt.Errorf("expected 20 bytes not %d", len(fingerprintBytes))
58 }
59 copy(fingerprint[:], fingerprintBytes)
60 return fingerprint, nil
61}
62
63func EncodeKeyFingerprint(fingerprint [20]byte) string {
64 return strings.ToUpper(hex.EncodeToString(fingerprint[:]))
65}
66
67func (k *Key) Validate() error {
68 _, err := k.GetPublicKey()
69 return err
70}
71
72func (k *Key) Clone() *Key {
73 clone := *k
74 return &clone
75}
76
77func (k *Key) GetPublicKey() (*packet.PublicKey, error) {
78 var err error
79 if k.PublicKey == nil {
80 k.PublicKey, err = parsePublicKey(k.ArmoredPublicKey)
81 }
82 return k.PublicKey, err
83}