1package gpg
2
3import (
4	"fmt"
5	"sort"
6	"time"
7)
8
9// Key is a GPG key (public or secret)
10type Key struct {
11	KeyType        string
12	KeyLength      int
13	Validity       string
14	CreationDate   time.Time
15	ExpirationDate time.Time
16	Ownertrust     string
17	Fingerprint    string
18	Identities     map[string]Identity
19	SubKeys        map[string]struct{}
20}
21
22// IsUseable returns true if GPG would assume this key is useable for encryption
23func (k Key) IsUseable(alwaysTrust bool) bool {
24	if !k.ExpirationDate.IsZero() && k.ExpirationDate.Before(time.Now()) {
25		return false
26	}
27	if alwaysTrust {
28		return true
29	}
30	switch k.Validity {
31	case "m":
32		return true
33	case "f":
34		return true
35	case "u":
36		return true
37	}
38	return false
39}
40
41// String implement fmt.Stringer. This method produces output that is close to, but
42// not exactly the same, as the output form GPG itself
43func (k Key) String() string {
44	fp := ""
45	if len(k.Fingerprint) > 24 {
46		fp = k.Fingerprint[24:]
47	}
48	out := fmt.Sprintf("%s   %dD/0x%s %s", k.KeyType, k.KeyLength, fp, k.CreationDate.Format("2006-01-02"))
49	if !k.ExpirationDate.IsZero() {
50		out += fmt.Sprintf(" [expires: %s]", k.ExpirationDate.Format("2006-01-02"))
51	}
52	out += "\n      Key fingerprint = " + k.Fingerprint
53	for _, id := range k.Identities {
54		out += fmt.Sprintf("\n" + id.String())
55	}
56	return out
57}
58
59// OneLine prints a terse representation of this key on one line (includes only
60// the first identity!)
61func (k Key) OneLine() string {
62	if len(k.Fingerprint) < 24 {
63		return fmt.Sprintf("(invalid:%s)", k.Fingerprint)
64	}
65	return fmt.Sprintf("0x%s - %s", k.Fingerprint[24:], k.Identity().ID())
66}
67
68// Identity returns the first identity
69func (k Key) Identity() Identity {
70	ids := make([]Identity, 0, len(k.Identities))
71	for _, i := range k.Identities {
72		ids = append(ids, i)
73	}
74	sort.Slice(ids, func(i, j int) bool {
75		return ids[i].CreationDate.After(ids[j].CreationDate)
76	})
77	for _, i := range ids {
78		return i
79	}
80	return Identity{}
81}
82
83// ID returns the short fingerprint
84func (k Key) ID() string {
85	if len(k.Fingerprint) < 25 {
86		return ""
87	}
88	return fmt.Sprintf("0x%s", k.Fingerprint[24:])
89}
90