-
Notifications
You must be signed in to change notification settings - Fork 41
/
verify_v4.go
78 lines (72 loc) · 1.98 KB
/
verify_v4.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
package rpmutils
import (
"bytes"
"hash"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
)
func parseSignature(blob []byte, knownKeys openpgp.EntityList) (*Signature, error) {
reader := bytes.NewReader(blob)
genpkt, err := packet.Read(reader)
if err != nil {
return nil, err
} else if reader.Len() > 0 {
return nil, ErrTrailingGarbage
}
return parseSignatureMaybeV3(genpkt, knownKeys)
}
func parseSignatureV4(genpkt packet.Packet, knownKeys openpgp.EntityList) (*Signature, error) {
pkt, ok := genpkt.(*packet.Signature)
if !ok || (pkt.IssuerKeyId == nil && len(pkt.IssuerFingerprint) == 0) {
return nil, ErrNoPGPSignature
}
sig := &Signature{
Hash: pkt.Hash,
CreationTime: pkt.CreationTime,
KeyFingerprint: pkt.IssuerFingerprint,
}
if pkt.IssuerKeyId != nil {
sig.KeyId = *pkt.IssuerKeyId
}
sig.validate = func(h hash.Hash) error {
if knownKeys == nil {
return nil
}
if entity, key := findKey(pkt, knownKeys); key != nil {
setEntity(sig, entity)
return key.VerifySignature(h, pkt)
}
return KeyNotFoundError{
KeyID: sig.KeyId,
Fingerprint: sig.KeyFingerprint,
}
}
return sig, nil
}
// set identity attributes on signature
func setEntity(sig *Signature, entity *openpgp.Entity) {
sig.Signer = entity
if sig.KeyId == 0 {
sig.KeyId = entity.PrimaryKey.KeyId
}
if sig.KeyFingerprint == nil {
sig.KeyFingerprint = entity.PrimaryKey.Fingerprint
}
if identity := entity.PrimaryIdentity(); identity != nil {
sig.PrimaryName = identity.Name
}
}
// find a key by its fingerprint (if available) or key ID
func findKey(sig *packet.Signature, knownKeys openpgp.EntityList) (*openpgp.Entity, *packet.PublicKey) {
for _, entity := range knownKeys {
if sig.CheckKeyIdOrFingerprint(entity.PrimaryKey) {
return entity, entity.PrimaryKey
}
for _, sub := range entity.Subkeys {
if sig.CheckKeyIdOrFingerprint(sub.PublicKey) {
return entity, sub.PublicKey
}
}
}
return nil, nil
}