/
keymerge.go
68 lines (58 loc) · 2.04 KB
/
keymerge.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
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package libkb
import (
"crypto"
"github.com/keybase/go-crypto/openpgp/packet"
)
func combineSignatures(toSignatures []*packet.Signature, fromSignatures []*packet.Signature) (ret []*packet.Signature) {
ret = toSignatures
existingSignatures := make(map[crypto.Hash]bool)
for _, signature := range toSignatures {
existingSignatures[signature.Hash] = true
}
for _, signature := range fromSignatures {
if _, haveSignature := existingSignatures[signature.Hash]; haveSignature {
continue
}
ret = append(ret, signature)
}
return
}
// MergeKey adds the identities, revocations, and subkeys of another PGPKeyBundle to this key
func (to *PGPKeyBundle) MergeKey(from *PGPKeyBundle) {
// First, merge identities, adding any signatures found in matching identities
for name, fromIdentity := range from.Identities {
if toIdentity, ok := to.Identities[name]; ok {
to.Identities[name].Signatures = combineSignatures(toIdentity.Signatures, fromIdentity.Signatures)
// There's a primary self-signature that we use. Always take the later
// of the two.
ssTo := to.Identities[name].SelfSignature
ssFrom := fromIdentity.SelfSignature
if ssFrom.CreationTime.After(ssTo.CreationTime) {
to.Identities[name].SelfSignature = ssFrom
}
} else {
to.Identities[fromIdentity.Name] = fromIdentity
}
}
// Then, merge revocations
to.Revocations = combineSignatures(to.Revocations, from.Revocations)
// Finally, merge subkeys
existingSubkeys := make(map[[20]byte]int)
for i, subkey := range to.Subkeys {
existingSubkeys[subkey.PublicKey.Fingerprint] = i
}
for _, subkey := range from.Subkeys {
if i, ok := existingSubkeys[subkey.PublicKey.Fingerprint]; ok {
if subkey.Sig.CreationTime.After(to.Subkeys[i].Sig.CreationTime) {
to.Subkeys[i].Sig = subkey.Sig
if subkey.Revocation != nil {
to.Subkeys[i].Revocation = subkey.Revocation
}
}
} else {
to.Subkeys = append(to.Subkeys, subkey)
}
}
}