1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package openpgp
6
7import (
8	goerrors "errors"
9	"io"
10	"time"
11
12	"github.com/ProtonMail/go-crypto/openpgp/armor"
13	"github.com/ProtonMail/go-crypto/openpgp/errors"
14	"github.com/ProtonMail/go-crypto/openpgp/packet"
15)
16
17// PublicKeyType is the armor type for a PGP public key.
18var PublicKeyType = "PGP PUBLIC KEY BLOCK"
19
20// PrivateKeyType is the armor type for a PGP private key.
21var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
22
23// An Entity represents the components of an OpenPGP key: a primary public key
24// (which must be a signing key), one or more identities claimed by that key,
25// and zero or more subkeys, which may be encryption keys.
26type Entity struct {
27	PrimaryKey  *packet.PublicKey
28	PrivateKey  *packet.PrivateKey
29	Identities  map[string]*Identity // indexed by Identity.Name
30	Revocations []*packet.Signature
31	Subkeys     []Subkey
32}
33
34// An Identity represents an identity claimed by an Entity and zero or more
35// assertions by other entities about that claim.
36type Identity struct {
37	Name          string // by convention, has the form "Full Name (comment) <email@example.com>"
38	UserId        *packet.UserId
39	SelfSignature *packet.Signature
40	Revocations   []*packet.Signature
41	Signatures    []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures
42}
43
44// A Subkey is an additional public key in an Entity. Subkeys can be used for
45// encryption.
46type Subkey struct {
47	PublicKey   *packet.PublicKey
48	PrivateKey  *packet.PrivateKey
49	Sig         *packet.Signature
50	Revocations []*packet.Signature
51}
52
53// A Key identifies a specific public key in an Entity. This is either the
54// Entity's primary key or a subkey.
55type Key struct {
56	Entity        *Entity
57	PublicKey     *packet.PublicKey
58	PrivateKey    *packet.PrivateKey
59	SelfSignature *packet.Signature
60	Revocations   []*packet.Signature
61}
62
63// A KeyRing provides access to public and private keys.
64type KeyRing interface {
65	// KeysById returns the set of keys that have the given key id.
66	KeysById(id uint64) []Key
67	// KeysByIdAndUsage returns the set of keys with the given id
68	// that also meet the key usage given by requiredUsage.
69	// The requiredUsage is expressed as the bitwise-OR of
70	// packet.KeyFlag* values.
71	KeysByIdUsage(id uint64, requiredUsage byte) []Key
72	// DecryptionKeys returns all private keys that are valid for
73	// decryption.
74	DecryptionKeys() []Key
75}
76
77// PrimaryIdentity returns an Identity, preferring non-revoked identities,
78// identities marked as primary, or the latest-created identity, in that order.
79func (e *Entity) PrimaryIdentity() *Identity {
80	var primaryIdentity *Identity
81	for _, ident := range e.Identities {
82		if shouldPreferIdentity(primaryIdentity, ident) {
83			primaryIdentity = ident
84		}
85	}
86	return primaryIdentity
87}
88
89func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
90	if (existingId == nil) {
91		return true
92	}
93
94	if (len(existingId.Revocations) > len(potentialNewId.Revocations)) {
95		return true
96	}
97
98	if (len(existingId.Revocations) < len(potentialNewId.Revocations)) {
99		return false
100	}
101
102	if (existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId &&
103		!(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId)) {
104		return false
105	}
106
107	if (!(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) &&
108		potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) {
109		return true
110	}
111
112	return potentialNewId.SelfSignature.CreationTime.After(existingId.SelfSignature.CreationTime)
113}
114
115// EncryptionKey returns the best candidate Key for encrypting a message to the
116// given Entity.
117func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
118	// Fail to find any encryption key if the...
119	i := e.PrimaryIdentity()
120	if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
121		i.SelfSignature.SigExpired(now) || // user ID self-signature has expired
122		e.Revoked(now) || // primary key has been revoked
123		i.Revoked(now) { // user ID has been revoked
124		return Key{}, false
125	}
126
127	// Iterate the keys to find the newest, unexpired one
128	candidateSubkey := -1
129	var maxTime time.Time
130	for i, subkey := range e.Subkeys {
131		if subkey.Sig.FlagsValid &&
132			subkey.Sig.FlagEncryptCommunications &&
133			subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
134			!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
135			!subkey.Sig.SigExpired(now) &&
136			!subkey.Revoked(now) &&
137			(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
138			candidateSubkey = i
139			maxTime = subkey.Sig.CreationTime
140		}
141	}
142
143	if candidateSubkey != -1 {
144		subkey := e.Subkeys[candidateSubkey]
145		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
146	}
147
148	// If we don't have any candidate subkeys for encryption and
149	// the primary key doesn't have any usage metadata then we
150	// assume that the primary key is ok. Or, if the primary key is
151	// marked as ok to encrypt with, then we can obviously use it.
152	if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
153		e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
154		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
155	}
156
157	return Key{}, false
158}
159
160// SigningKey return the best candidate Key for signing a message with this
161// Entity.
162func (e *Entity) SigningKey(now time.Time) (Key, bool) {
163	return e.SigningKeyById(now, 0)
164}
165
166// SigningKeyById return the Key for signing a message with this
167// Entity and keyID.
168func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
169	// Fail to find any signing key if the...
170	i := e.PrimaryIdentity()
171	if e.PrimaryKey.KeyExpired(i.SelfSignature, now) || // primary key has expired
172		i.SelfSignature.SigExpired(now) || // user ID self-signature has expired
173		e.Revoked(now) || // primary key has been revoked
174		i.Revoked(now) { // user ID has been revoked
175		return Key{}, false
176	}
177
178	// Iterate the keys to find the newest, unexpired one
179	candidateSubkey := -1
180	var maxTime time.Time
181	for idx, subkey := range e.Subkeys {
182		if subkey.Sig.FlagsValid &&
183			subkey.Sig.FlagSign &&
184			subkey.PublicKey.PubKeyAlgo.CanSign() &&
185			!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
186			!subkey.Sig.SigExpired(now) &&
187			!subkey.Revoked(now) &&
188			(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) &&
189			(id == 0 || subkey.PublicKey.KeyId == id) {
190			candidateSubkey = idx
191			maxTime = subkey.Sig.CreationTime
192		}
193	}
194
195	if candidateSubkey != -1 {
196		subkey := e.Subkeys[candidateSubkey]
197		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
198	}
199
200	// If we have no candidate subkey then we assume that it's ok to sign
201	// with the primary key.  Or, if the primary key is marked as ok to
202	// sign with, then we can use it.
203	if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
204		e.PrimaryKey.PubKeyAlgo.CanSign() &&
205		(id == 0 || e.PrimaryKey.KeyId == id) {
206		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
207	}
208
209	// No keys with a valid Signing Flag or no keys matched the id passed in
210	return Key{}, false
211}
212
213func revoked(revocations []*packet.Signature, now time.Time) bool {
214	for _, revocation := range revocations {
215		if revocation.RevocationReason != nil && *revocation.RevocationReason == packet.KeyCompromised {
216			// If the key is compromised, the key is considered revoked even before the revocation date.
217			return true
218		}
219		if !revocation.SigExpired(now) {
220			return true
221		}
222	}
223	return false
224}
225
226// Revoked returns whether the entity has any direct key revocation signatures.
227// Note that third-party revocation signatures are not supported.
228// Note also that Identity and Subkey revocation should be checked separately.
229func (e *Entity) Revoked(now time.Time) bool {
230	return revoked(e.Revocations, now)
231}
232
233// Revoked returns whether the identity has been revoked by a self-signature.
234// Note that third-party revocation signatures are not supported.
235func (i *Identity) Revoked(now time.Time) bool {
236	return revoked(i.Revocations, now)
237}
238
239// Revoked returns whether the subkey has been revoked by a self-signature.
240// Note that third-party revocation signatures are not supported.
241func (s *Subkey) Revoked(now time.Time) bool {
242	return revoked(s.Revocations, now)
243}
244
245// Revoked returns whether the key or subkey has been revoked by a self-signature.
246// Note that third-party revocation signatures are not supported.
247// Note also that Identity revocation should be checked separately.
248// Normally, it's not necessary to call this function, except on keys returned by
249// KeysById or KeysByIdUsage.
250func (key *Key) Revoked(now time.Time) bool {
251	return revoked(key.Revocations, now)
252}
253
254// An EntityList contains one or more Entities.
255type EntityList []*Entity
256
257// KeysById returns the set of keys that have the given key id.
258func (el EntityList) KeysById(id uint64) (keys []Key) {
259	for _, e := range el {
260		if e.PrimaryKey.KeyId == id {
261			ident := e.PrimaryIdentity()
262			selfSig := ident.SelfSignature
263			keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations})
264		}
265
266		for _, subKey := range e.Subkeys {
267			if subKey.PublicKey.KeyId == id {
268				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
269			}
270		}
271	}
272	return
273}
274
275// KeysByIdAndUsage returns the set of keys with the given id that also meet
276// the key usage given by requiredUsage.  The requiredUsage is expressed as
277// the bitwise-OR of packet.KeyFlag* values.
278func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
279	for _, key := range el.KeysById(id) {
280		if key.SelfSignature.FlagsValid && requiredUsage != 0 {
281			var usage byte
282			if key.SelfSignature.FlagCertify {
283				usage |= packet.KeyFlagCertify
284			}
285			if key.SelfSignature.FlagSign {
286				usage |= packet.KeyFlagSign
287			}
288			if key.SelfSignature.FlagEncryptCommunications {
289				usage |= packet.KeyFlagEncryptCommunications
290			}
291			if key.SelfSignature.FlagEncryptStorage {
292				usage |= packet.KeyFlagEncryptStorage
293			}
294			if usage&requiredUsage != requiredUsage {
295				continue
296			}
297		}
298
299		keys = append(keys, key)
300	}
301	return
302}
303
304// DecryptionKeys returns all private keys that are valid for decryption.
305func (el EntityList) DecryptionKeys() (keys []Key) {
306	for _, e := range el {
307		for _, subKey := range e.Subkeys {
308			if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
309				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
310			}
311		}
312	}
313	return
314}
315
316// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
317func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
318	block, err := armor.Decode(r)
319	if err == io.EOF {
320		return nil, errors.InvalidArgumentError("no armored data found")
321	}
322	if err != nil {
323		return nil, err
324	}
325	if block.Type != PublicKeyType && block.Type != PrivateKeyType {
326		return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
327	}
328
329	return ReadKeyRing(block.Body)
330}
331
332// ReadKeyRing reads one or more public/private keys. Unsupported keys are
333// ignored as long as at least a single valid key is found.
334func ReadKeyRing(r io.Reader) (el EntityList, err error) {
335	packets := packet.NewReader(r)
336	var lastUnsupportedError error
337
338	for {
339		var e *Entity
340		e, err = ReadEntity(packets)
341		if err != nil {
342			// TODO: warn about skipped unsupported/unreadable keys
343			if _, ok := err.(errors.UnsupportedError); ok {
344				lastUnsupportedError = err
345				err = readToNextPublicKey(packets)
346			} else if _, ok := err.(errors.StructuralError); ok {
347				// Skip unreadable, badly-formatted keys
348				lastUnsupportedError = err
349				err = readToNextPublicKey(packets)
350			}
351			if err == io.EOF {
352				err = nil
353				break
354			}
355			if err != nil {
356				el = nil
357				break
358			}
359		} else {
360			el = append(el, e)
361		}
362	}
363
364	if len(el) == 0 && err == nil {
365		err = lastUnsupportedError
366	}
367	return
368}
369
370// readToNextPublicKey reads packets until the start of the entity and leaves
371// the first packet of the new entity in the Reader.
372func readToNextPublicKey(packets *packet.Reader) (err error) {
373	var p packet.Packet
374	for {
375		p, err = packets.Next()
376		if err == io.EOF {
377			return
378		} else if err != nil {
379			if _, ok := err.(errors.UnsupportedError); ok {
380				err = nil
381				continue
382			}
383			return
384		}
385
386		if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
387			packets.Unread(p)
388			return
389		}
390	}
391}
392
393// ReadEntity reads an entity (public key, identities, subkeys etc) from the
394// given Reader.
395func ReadEntity(packets *packet.Reader) (*Entity, error) {
396	e := new(Entity)
397	e.Identities = make(map[string]*Identity)
398
399	p, err := packets.Next()
400	if err != nil {
401		return nil, err
402	}
403
404	var ok bool
405	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
406		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
407			packets.Unread(p)
408			return nil, errors.StructuralError("first packet was not a public/private key")
409		}
410		e.PrimaryKey = &e.PrivateKey.PublicKey
411	}
412
413	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
414		return nil, errors.StructuralError("primary key cannot be used for signatures")
415	}
416
417	var revocations []*packet.Signature
418EachPacket:
419	for {
420		p, err := packets.Next()
421		if err == io.EOF {
422			break
423		} else if err != nil {
424			return nil, err
425		}
426
427		switch pkt := p.(type) {
428		case *packet.UserId:
429			if err := addUserID(e, packets, pkt); err != nil {
430				return nil, err
431			}
432		case *packet.Signature:
433			if pkt.SigType == packet.SigTypeKeyRevocation {
434				revocations = append(revocations, pkt)
435			} else if pkt.SigType == packet.SigTypeDirectSignature {
436				// TODO: RFC4880 5.2.1 permits signatures
437				// directly on keys (eg. to bind additional
438				// revocation keys).
439			}
440			// Else, ignoring the signature as it does not follow anything
441			// we would know to attach it to.
442		case *packet.PrivateKey:
443			if pkt.IsSubkey == false {
444				packets.Unread(p)
445				break EachPacket
446			}
447			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
448			if err != nil {
449				return nil, err
450			}
451		case *packet.PublicKey:
452			if pkt.IsSubkey == false {
453				packets.Unread(p)
454				break EachPacket
455			}
456			err = addSubkey(e, packets, pkt, nil)
457			if err != nil {
458				return nil, err
459			}
460		default:
461			// we ignore unknown packets
462		}
463	}
464
465	if len(e.Identities) == 0 {
466		return nil, errors.StructuralError("entity without any identities")
467	}
468
469	for _, revocation := range revocations {
470		err = e.PrimaryKey.VerifyRevocationSignature(revocation)
471		if err == nil {
472			e.Revocations = append(e.Revocations, revocation)
473		} else {
474			// TODO: RFC 4880 5.2.3.15 defines revocation keys.
475			return nil, errors.StructuralError("revocation signature signed by alternate key")
476		}
477	}
478
479	return e, nil
480}
481
482func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error {
483	// Make a new Identity object, that we might wind up throwing away.
484	// We'll only add it if we get a valid self-signature over this
485	// userID.
486	identity := new(Identity)
487	identity.Name = pkt.Id
488	identity.UserId = pkt
489
490	for {
491		p, err := packets.Next()
492		if err == io.EOF {
493			break
494		} else if err != nil {
495			return err
496		}
497
498		sig, ok := p.(*packet.Signature)
499		if !ok {
500			packets.Unread(p)
501			break
502		}
503
504		if sig.SigType != packet.SigTypeGenericCert &&
505			sig.SigType != packet.SigTypePersonaCert &&
506			sig.SigType != packet.SigTypeCasualCert &&
507			sig.SigType != packet.SigTypePositiveCert &&
508			sig.SigType != packet.SigTypeCertificationRevocation {
509			return errors.StructuralError("user ID signature with wrong type")
510		}
511
512
513		if sig.CheckKeyIdOrFingerprint(e.PrimaryKey) {
514			if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
515				return errors.StructuralError("user ID self-signature invalid: " + err.Error())
516			}
517			if sig.SigType == packet.SigTypeCertificationRevocation {
518				identity.Revocations = append(identity.Revocations, sig)
519			} else if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) {
520				identity.SelfSignature = sig
521			}
522			identity.Signatures = append(identity.Signatures, sig)
523			e.Identities[pkt.Id] = identity
524		} else {
525			identity.Signatures = append(identity.Signatures, sig)
526		}
527	}
528
529	return nil
530}
531
532func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
533	var subKey Subkey
534	subKey.PublicKey = pub
535	subKey.PrivateKey = priv
536
537	for {
538		p, err := packets.Next()
539		if err == io.EOF {
540			break
541		} else if err != nil {
542			return errors.StructuralError("subkey signature invalid: " + err.Error())
543		}
544
545		sig, ok := p.(*packet.Signature)
546		if !ok {
547			packets.Unread(p)
548			break
549		}
550
551		if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation {
552			return errors.StructuralError("subkey signature with wrong type")
553		}
554
555		if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil {
556			return errors.StructuralError("subkey signature invalid: " + err.Error())
557		}
558
559		switch sig.SigType {
560		case packet.SigTypeSubkeyRevocation:
561			subKey.Revocations = append(subKey.Revocations, sig)
562		case packet.SigTypeSubkeyBinding:
563			if subKey.Sig == nil || sig.CreationTime.After(subKey.Sig.CreationTime) {
564				subKey.Sig = sig
565			}
566		}
567	}
568
569	if subKey.Sig == nil {
570		return errors.StructuralError("subkey packet not followed by signature")
571	}
572
573	e.Subkeys = append(e.Subkeys, subKey)
574
575	return nil
576}
577
578// SerializePrivate serializes an Entity, including private key material, but
579// excluding signatures from other entities, to the given Writer.
580// Identities and subkeys are re-signed in case they changed since NewEntry.
581// If config is nil, sensible defaults will be used.
582func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
583	if e.PrivateKey.Dummy() {
584		return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities")
585	}
586	return e.serializePrivate(w, config, true)
587}
588
589// SerializePrivateWithoutSigning serializes an Entity, including private key
590// material, but excluding signatures from other entities, to the given Writer.
591// Self-signatures of identities and subkeys are not re-signed. This is useful
592// when serializing GNU dummy keys, among other things.
593// If config is nil, sensible defaults will be used.
594func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) {
595	return e.serializePrivate(w, config, false)
596}
597
598func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) {
599	if e.PrivateKey == nil {
600		return goerrors.New("openpgp: private key is missing")
601	}
602	err = e.PrivateKey.Serialize(w)
603	if err != nil {
604		return
605	}
606	for _, revocation := range e.Revocations {
607		err := revocation.Serialize(w)
608		if err != nil {
609			return err
610		}
611	}
612	for _, ident := range e.Identities {
613		err = ident.UserId.Serialize(w)
614		if err != nil {
615			return
616		}
617		if reSign {
618			err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
619			if err != nil {
620				return
621			}
622		}
623		for _, revocation := range ident.Revocations {
624			err := revocation.Serialize(w)
625			if err != nil {
626				return err
627			}
628		}
629		err = ident.SelfSignature.Serialize(w)
630		if err != nil {
631			return
632		}
633	}
634	for _, subkey := range e.Subkeys {
635		err = subkey.PrivateKey.Serialize(w)
636		if err != nil {
637			return
638		}
639		if reSign {
640			err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
641			if err != nil {
642				return
643			}
644			if subkey.Sig.EmbeddedSignature != nil {
645				err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey,
646					subkey.PrivateKey, config)
647				if err != nil {
648					return
649				}
650			}
651		}
652		for _, revocation := range subkey.Revocations {
653			err := revocation.Serialize(w)
654			if err != nil {
655				return err
656			}
657		}
658		err = subkey.Sig.Serialize(w)
659		if err != nil {
660			return
661		}
662	}
663	return nil
664}
665
666// Serialize writes the public part of the given Entity to w, including
667// signatures from other entities. No private key material will be output.
668func (e *Entity) Serialize(w io.Writer) error {
669	err := e.PrimaryKey.Serialize(w)
670	if err != nil {
671		return err
672	}
673	for _, revocation := range e.Revocations {
674		err := revocation.Serialize(w)
675		if err != nil {
676			return err
677		}
678	}
679	for _, ident := range e.Identities {
680		err = ident.UserId.Serialize(w)
681		if err != nil {
682			return err
683		}
684		for _, sig := range ident.Signatures {
685			err = sig.Serialize(w)
686			if err != nil {
687				return err
688			}
689		}
690	}
691	for _, subkey := range e.Subkeys {
692		err = subkey.PublicKey.Serialize(w)
693		if err != nil {
694			return err
695		}
696		for _, revocation := range subkey.Revocations {
697			err := revocation.Serialize(w)
698			if err != nil {
699				return err
700			}
701		}
702		err = subkey.Sig.Serialize(w)
703		if err != nil {
704			return err
705		}
706	}
707	return nil
708}
709
710// SignIdentity adds a signature to e, from signer, attesting that identity is
711// associated with e. The provided identity must already be an element of
712// e.Identities and the private key of signer must have been decrypted if
713// necessary.
714// If config is nil, sensible defaults will be used.
715func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
716	if signer.PrivateKey == nil {
717		return errors.InvalidArgumentError("signing Entity must have a private key")
718	}
719	if signer.PrivateKey.Encrypted {
720		return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
721	}
722	ident, ok := e.Identities[identity]
723	if !ok {
724		return errors.InvalidArgumentError("given identity string not found in Entity")
725	}
726
727	sig := &packet.Signature{
728		Version:      signer.PrivateKey.Version,
729		SigType:      packet.SigTypeGenericCert,
730		PubKeyAlgo:   signer.PrivateKey.PubKeyAlgo,
731		Hash:         config.Hash(),
732		CreationTime: config.Now(),
733		IssuerKeyId:  &signer.PrivateKey.KeyId,
734	}
735	if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
736		return err
737	}
738	ident.Signatures = append(ident.Signatures, sig)
739	return nil
740}
741
742// RevokeKey generates a key revocation signature (packet.SigTypeKeyRevocation) with the
743// specified reason code and text (RFC4880 section-5.2.3.23).
744// If config is nil, sensible defaults will be used.
745func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
746	revSig := &packet.Signature{
747		Version:              e.PrimaryKey.Version,
748		CreationTime:         config.Now(),
749		SigType:              packet.SigTypeKeyRevocation,
750		PubKeyAlgo:           e.PrimaryKey.PubKeyAlgo,
751		Hash:                 config.Hash(),
752		RevocationReason:     &reason,
753		RevocationReasonText: reasonText,
754		IssuerKeyId:          &e.PrimaryKey.KeyId,
755	}
756
757	if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil {
758		return err
759	}
760	e.Revocations = append(e.Revocations, revSig)
761	return nil
762}
763
764// RevokeSubkey generates a subkey revocation signature (packet.SigTypeSubkeyRevocation) for
765// a subkey with the specified reason code and text (RFC4880 section-5.2.3.23).
766// If config is nil, sensible defaults will be used.
767func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
768	if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil {
769		return errors.InvalidArgumentError("given subkey is not associated with this key")
770	}
771
772	revSig := &packet.Signature{
773		Version:              e.PrimaryKey.Version,
774		CreationTime:         config.Now(),
775		SigType:              packet.SigTypeSubkeyRevocation,
776		PubKeyAlgo:           e.PrimaryKey.PubKeyAlgo,
777		Hash:                 config.Hash(),
778		RevocationReason:     &reason,
779		RevocationReasonText: reasonText,
780		IssuerKeyId:          &e.PrimaryKey.KeyId,
781	}
782
783	if err := revSig.RevokeSubkey(sk.PublicKey, e.PrivateKey, config); err != nil {
784		return err
785	}
786
787	sk.Revocations = append(sk.Revocations, revSig)
788	return nil
789}
790