-
Notifications
You must be signed in to change notification settings - Fork 3
/
hkp.go
130 lines (114 loc) · 2.53 KB
/
hkp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Package hkp implements OpenPGP HTTP Keyserver Protocol (HKP), as defined in
// https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00
package hkp
import (
"encoding/binary"
"encoding/hex"
"io"
"strings"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor"
)
// Base is the base path for the HTTP API.
const Base = "/pks"
const (
lookupPath = Base + "/lookup"
addPath = Base + "/add"
)
type LookupOptions struct {
NoModification bool
}
func (opts *LookupOptions) format() string {
var l []string
l = append(l, "mr") // implicit
if opts.NoModification {
l = append(l, "nm")
}
return strings.Join(l, ",")
}
func parseLookupOptions(s string) *LookupOptions {
var opts LookupOptions
for _, opt := range strings.Split(s, ",") {
switch opt {
case "nm":
opts.NoModification = true
}
}
return &opts
}
type LookupRequest struct {
Search string
Options LookupOptions
Exact bool
}
func serializeArmoredKeyRing(w io.Writer, el openpgp.EntityList) error {
aw, err := armor.Encode(w, openpgp.PublicKeyType, nil)
if err != nil {
return err
}
defer aw.Close()
for _, e := range el {
if err := e.Serialize(aw); err != nil {
return err
}
}
return nil
}
type KeyIDSearch []byte
// ParseKeyIDSearch parses a key ID search prefixed with "0x". If the supplied
// search isn't a key ID, returns nil.
func ParseKeyIDSearch(search string) KeyIDSearch {
if !strings.HasPrefix(search, "0x") {
return nil
}
b, err := hex.DecodeString(search[2:])
if err != nil {
return nil
}
switch len(b) {
case 20, 8, 4:
return KeyIDSearch(b)
default:
return nil
}
}
// Fingerprint extracts a fingerprint from a key ID search. It returns nil if
// the search doesn't contain a fingerprint.
func (search KeyIDSearch) Fingerprint() []byte {
if len(search) != 20 {
return nil
}
return []byte(search)
}
// KeyId extracts a 64-bit key ID from a key ID search. It returns nil if the
// search doesn't contain a 64-bit key ID.
func (search KeyIDSearch) KeyId() *uint64 {
var b []byte
switch len(search) {
case 20:
b = search[12:20]
case 8:
b = search
default:
return nil
}
keyID := binary.BigEndian.Uint64(b)
return &keyID
}
// KeyIdShort extracts a 32-bit key ID from a key ID search. It returns nil if
// the search doesn't contain a 32-bit key ID.
func (search KeyIDSearch) KeyIdShort() *uint32 {
var b []byte
switch len(search) {
case 20:
b = search[16:20]
case 8:
b = search[4:8]
case 4:
b = search
default:
return nil
}
keyID := binary.BigEndian.Uint32(b)
return &keyID
}