key.go

 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 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}