1
2
3
4
5 package openpgp
6
7 import (
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
18 var PublicKeyType = "PGP PUBLIC KEY BLOCK"
19
20
21 var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
22
23
24
25
26 type Entity struct {
27 PrimaryKey *packet.PublicKey
28 PrivateKey *packet.PrivateKey
29 Identities map[string]*Identity
30 Revocations []*packet.Signature
31 Subkeys []Subkey
32 }
33
34
35
36 type Identity struct {
37 Name string
38 UserId *packet.UserId
39 SelfSignature *packet.Signature
40 Revocations []*packet.Signature
41 Signatures []*packet.Signature
42 }
43
44
45
46 type Subkey struct {
47 PublicKey *packet.PublicKey
48 PrivateKey *packet.PrivateKey
49 Sig *packet.Signature
50 Revocations []*packet.Signature
51 }
52
53
54
55 type Key struct {
56 Entity *Entity
57 PublicKey *packet.PublicKey
58 PrivateKey *packet.PrivateKey
59 SelfSignature *packet.Signature
60 Revocations []*packet.Signature
61 }
62
63
64 type KeyRing interface {
65
66 KeysById(id uint64) []Key
67
68
69
70
71 KeysByIdUsage(id uint64, requiredUsage byte) []Key
72
73
74 DecryptionKeys() []Key
75 }
76
77
78
79 func (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
89 func 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 == nil {
103 return true
104 }
105
106 if existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId &&
107 !(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) {
108 return false
109 }
110
111 if !(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) &&
112 potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId {
113 return true
114 }
115
116 return potentialNewId.SelfSignature.CreationTime.After(existingId.SelfSignature.CreationTime)
117 }
118
119
120
121 func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
122
123 i := e.PrimaryIdentity()
124 if e.PrimaryKey.KeyExpired(i.SelfSignature, now) ||
125 i.SelfSignature == nil ||
126 i.SelfSignature.SigExpired(now) ||
127 e.Revoked(now) ||
128 i.Revoked(now) {
129 return Key{}, false
130 }
131
132
133 candidateSubkey := -1
134 var maxTime time.Time
135 for i, subkey := range e.Subkeys {
136 if subkey.Sig.FlagsValid &&
137 subkey.Sig.FlagEncryptCommunications &&
138 subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
139 !subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
140 !subkey.Sig.SigExpired(now) &&
141 !subkey.Revoked(now) &&
142 (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
143 candidateSubkey = i
144 maxTime = subkey.Sig.CreationTime
145 }
146 }
147
148 if candidateSubkey != -1 {
149 subkey := e.Subkeys[candidateSubkey]
150 return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
151 }
152
153
154
155 if i.SelfSignature.FlagsValid && i.SelfSignature.FlagEncryptCommunications &&
156 e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
157 return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
158 }
159
160 return Key{}, false
161 }
162
163
164
165 func (e *Entity) CertificationKey(now time.Time) (Key, bool) {
166 return e.CertificationKeyById(now, 0)
167 }
168
169
170
171 func (e *Entity) CertificationKeyById(now time.Time, id uint64) (Key, bool) {
172 return e.signingKeyByIdUsage(now, id, packet.KeyFlagCertify)
173 }
174
175
176
177 func (e *Entity) SigningKey(now time.Time) (Key, bool) {
178 return e.SigningKeyById(now, 0)
179 }
180
181
182
183 func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
184 return e.signingKeyByIdUsage(now, id, packet.KeyFlagSign)
185 }
186
187 func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) {
188
189 i := e.PrimaryIdentity()
190 if e.PrimaryKey.KeyExpired(i.SelfSignature, now) ||
191 i.SelfSignature == nil ||
192 i.SelfSignature.SigExpired(now) ||
193 e.Revoked(now) ||
194 i.Revoked(now) {
195 return Key{}, false
196 }
197
198
199 candidateSubkey := -1
200 var maxTime time.Time
201 for idx, subkey := range e.Subkeys {
202 if subkey.Sig.FlagsValid &&
203 (flags&packet.KeyFlagCertify == 0 || subkey.Sig.FlagCertify) &&
204 (flags&packet.KeyFlagSign == 0 || subkey.Sig.FlagSign) &&
205 subkey.PublicKey.PubKeyAlgo.CanSign() &&
206 !subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
207 !subkey.Sig.SigExpired(now) &&
208 !subkey.Revoked(now) &&
209 (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) &&
210 (id == 0 || subkey.PublicKey.KeyId == id) {
211 candidateSubkey = idx
212 maxTime = subkey.Sig.CreationTime
213 }
214 }
215
216 if candidateSubkey != -1 {
217 subkey := e.Subkeys[candidateSubkey]
218 return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
219 }
220
221
222
223 if i.SelfSignature.FlagsValid &&
224 (flags&packet.KeyFlagCertify == 0 || i.SelfSignature.FlagCertify) &&
225 (flags&packet.KeyFlagSign == 0 || i.SelfSignature.FlagSign) &&
226 e.PrimaryKey.PubKeyAlgo.CanSign() &&
227 (id == 0 || e.PrimaryKey.KeyId == id) {
228 return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature, e.Revocations}, true
229 }
230
231
232 return Key{}, false
233 }
234
235 func revoked(revocations []*packet.Signature, now time.Time) bool {
236 for _, revocation := range revocations {
237 if revocation.RevocationReason != nil && *revocation.RevocationReason == packet.KeyCompromised {
238
239 return true
240 }
241 if !revocation.SigExpired(now) {
242 return true
243 }
244 }
245 return false
246 }
247
248
249
250
251 func (e *Entity) Revoked(now time.Time) bool {
252 return revoked(e.Revocations, now)
253 }
254
255
256
257
258 func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) error {
259 var keysToEncrypt []*packet.PrivateKey
260
261 if e.PrivateKey != nil && !e.PrivateKey.Dummy() && !e.PrivateKey.Encrypted {
262 keysToEncrypt = append(keysToEncrypt, e.PrivateKey)
263 }
264
265
266 for _, sub := range e.Subkeys {
267 if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && !sub.PrivateKey.Encrypted {
268 keysToEncrypt = append(keysToEncrypt, sub.PrivateKey)
269 }
270 }
271 return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config)
272 }
273
274
275
276
277 func (e *Entity) DecryptPrivateKeys(passphrase []byte) error {
278 var keysToDecrypt []*packet.PrivateKey
279
280 if e.PrivateKey != nil && !e.PrivateKey.Dummy() && e.PrivateKey.Encrypted {
281 keysToDecrypt = append(keysToDecrypt, e.PrivateKey)
282 }
283
284
285 for _, sub := range e.Subkeys {
286 if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && sub.PrivateKey.Encrypted {
287 keysToDecrypt = append(keysToDecrypt, sub.PrivateKey)
288 }
289 }
290 return packet.DecryptPrivateKeys(keysToDecrypt, passphrase)
291 }
292
293
294
295 func (i *Identity) Revoked(now time.Time) bool {
296 return revoked(i.Revocations, now)
297 }
298
299
300
301 func (s *Subkey) Revoked(now time.Time) bool {
302 return revoked(s.Revocations, now)
303 }
304
305
306
307
308
309
310 func (key *Key) Revoked(now time.Time) bool {
311 return revoked(key.Revocations, now)
312 }
313
314
315 type EntityList []*Entity
316
317
318 func (el EntityList) KeysById(id uint64) (keys []Key) {
319 for _, e := range el {
320 if e.PrimaryKey.KeyId == id {
321 ident := e.PrimaryIdentity()
322 selfSig := ident.SelfSignature
323 keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations})
324 }
325
326 for _, subKey := range e.Subkeys {
327 if subKey.PublicKey.KeyId == id {
328 keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
329 }
330 }
331 }
332 return
333 }
334
335
336
337
338 func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
339 for _, key := range el.KeysById(id) {
340 if requiredUsage != 0 {
341 if key.SelfSignature == nil || !key.SelfSignature.FlagsValid {
342 continue
343 }
344
345 var usage byte
346 if key.SelfSignature.FlagCertify {
347 usage |= packet.KeyFlagCertify
348 }
349 if key.SelfSignature.FlagSign {
350 usage |= packet.KeyFlagSign
351 }
352 if key.SelfSignature.FlagEncryptCommunications {
353 usage |= packet.KeyFlagEncryptCommunications
354 }
355 if key.SelfSignature.FlagEncryptStorage {
356 usage |= packet.KeyFlagEncryptStorage
357 }
358 if usage&requiredUsage != requiredUsage {
359 continue
360 }
361 }
362
363 keys = append(keys, key)
364 }
365 return
366 }
367
368
369 func (el EntityList) DecryptionKeys() (keys []Key) {
370 for _, e := range el {
371 for _, subKey := range e.Subkeys {
372 if subKey.PrivateKey != nil && subKey.Sig.FlagsValid && (subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
373 keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
374 }
375 }
376 }
377 return
378 }
379
380
381 func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
382 block, err := armor.Decode(r)
383 if err == io.EOF {
384 return nil, errors.InvalidArgumentError("no armored data found")
385 }
386 if err != nil {
387 return nil, err
388 }
389 if block.Type != PublicKeyType && block.Type != PrivateKeyType {
390 return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
391 }
392
393 return ReadKeyRing(block.Body)
394 }
395
396
397
398 func ReadKeyRing(r io.Reader) (el EntityList, err error) {
399 packets := packet.NewReader(r)
400 var lastUnsupportedError error
401
402 for {
403 var e *Entity
404 e, err = ReadEntity(packets)
405 if err != nil {
406
407 if _, ok := err.(errors.UnsupportedError); ok {
408 lastUnsupportedError = err
409 err = readToNextPublicKey(packets)
410 } else if _, ok := err.(errors.StructuralError); ok {
411
412 lastUnsupportedError = err
413 err = readToNextPublicKey(packets)
414 }
415 if err == io.EOF {
416 err = nil
417 break
418 }
419 if err != nil {
420 el = nil
421 break
422 }
423 } else {
424 el = append(el, e)
425 }
426 }
427
428 if len(el) == 0 && err == nil {
429 err = lastUnsupportedError
430 }
431 return
432 }
433
434
435
436 func readToNextPublicKey(packets *packet.Reader) (err error) {
437 var p packet.Packet
438 for {
439 p, err = packets.Next()
440 if err == io.EOF {
441 return
442 } else if err != nil {
443 if _, ok := err.(errors.UnsupportedError); ok {
444 err = nil
445 continue
446 }
447 return
448 }
449
450 if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
451 packets.Unread(p)
452 return
453 }
454 }
455 }
456
457
458
459 func ReadEntity(packets *packet.Reader) (*Entity, error) {
460 e := new(Entity)
461 e.Identities = make(map[string]*Identity)
462
463 p, err := packets.Next()
464 if err != nil {
465 return nil, err
466 }
467
468 var ok bool
469 if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
470 if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
471 packets.Unread(p)
472 return nil, errors.StructuralError("first packet was not a public/private key")
473 }
474 e.PrimaryKey = &e.PrivateKey.PublicKey
475 }
476
477 if !e.PrimaryKey.PubKeyAlgo.CanSign() {
478 return nil, errors.StructuralError("primary key cannot be used for signatures")
479 }
480
481 var revocations []*packet.Signature
482 EachPacket:
483 for {
484 p, err := packets.Next()
485 if err == io.EOF {
486 break
487 } else if err != nil {
488 return nil, err
489 }
490
491 switch pkt := p.(type) {
492 case *packet.UserId:
493 if err := addUserID(e, packets, pkt); err != nil {
494 return nil, err
495 }
496 case *packet.Signature:
497 if pkt.SigType == packet.SigTypeKeyRevocation {
498 revocations = append(revocations, pkt)
499 } else if pkt.SigType == packet.SigTypeDirectSignature {
500
501
502
503 }
504
505
506 case *packet.PrivateKey:
507 if !pkt.IsSubkey {
508 packets.Unread(p)
509 break EachPacket
510 }
511 err = addSubkey(e, packets, &pkt.PublicKey, pkt)
512 if err != nil {
513 return nil, err
514 }
515 case *packet.PublicKey:
516 if !pkt.IsSubkey {
517 packets.Unread(p)
518 break EachPacket
519 }
520 err = addSubkey(e, packets, pkt, nil)
521 if err != nil {
522 return nil, err
523 }
524 default:
525
526 }
527 }
528
529 if len(e.Identities) == 0 {
530 return nil, errors.StructuralError("entity without any identities")
531 }
532
533 for _, revocation := range revocations {
534 err = e.PrimaryKey.VerifyRevocationSignature(revocation)
535 if err == nil {
536 e.Revocations = append(e.Revocations, revocation)
537 } else {
538
539 return nil, errors.StructuralError("revocation signature signed by alternate key")
540 }
541 }
542
543 return e, nil
544 }
545
546 func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error {
547
548
549
550 identity := new(Identity)
551 identity.Name = pkt.Id
552 identity.UserId = pkt
553
554 for {
555 p, err := packets.Next()
556 if err == io.EOF {
557 break
558 } else if err != nil {
559 return err
560 }
561
562 sig, ok := p.(*packet.Signature)
563 if !ok {
564 packets.Unread(p)
565 break
566 }
567
568 if sig.SigType != packet.SigTypeGenericCert &&
569 sig.SigType != packet.SigTypePersonaCert &&
570 sig.SigType != packet.SigTypeCasualCert &&
571 sig.SigType != packet.SigTypePositiveCert &&
572 sig.SigType != packet.SigTypeCertificationRevocation {
573 return errors.StructuralError("user ID signature with wrong type")
574 }
575
576 if sig.CheckKeyIdOrFingerprint(e.PrimaryKey) {
577 if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
578 return errors.StructuralError("user ID self-signature invalid: " + err.Error())
579 }
580 if sig.SigType == packet.SigTypeCertificationRevocation {
581 identity.Revocations = append(identity.Revocations, sig)
582 } else if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) {
583 identity.SelfSignature = sig
584 }
585 identity.Signatures = append(identity.Signatures, sig)
586 e.Identities[pkt.Id] = identity
587 } else {
588 identity.Signatures = append(identity.Signatures, sig)
589 }
590 }
591
592 return nil
593 }
594
595 func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
596 var subKey Subkey
597 subKey.PublicKey = pub
598 subKey.PrivateKey = priv
599
600 for {
601 p, err := packets.Next()
602 if err == io.EOF {
603 break
604 } else if err != nil {
605 return errors.StructuralError("subkey signature invalid: " + err.Error())
606 }
607
608 sig, ok := p.(*packet.Signature)
609 if !ok {
610 packets.Unread(p)
611 break
612 }
613
614 if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation {
615 return errors.StructuralError("subkey signature with wrong type")
616 }
617
618 if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil {
619 return errors.StructuralError("subkey signature invalid: " + err.Error())
620 }
621
622 switch sig.SigType {
623 case packet.SigTypeSubkeyRevocation:
624 subKey.Revocations = append(subKey.Revocations, sig)
625 case packet.SigTypeSubkeyBinding:
626 if subKey.Sig == nil || sig.CreationTime.After(subKey.Sig.CreationTime) {
627 subKey.Sig = sig
628 }
629 }
630 }
631
632 if subKey.Sig == nil {
633 return errors.StructuralError("subkey packet not followed by signature")
634 }
635
636 e.Subkeys = append(e.Subkeys, subKey)
637
638 return nil
639 }
640
641
642
643
644
645 func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
646 if e.PrivateKey.Dummy() {
647 return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities")
648 }
649 return e.serializePrivate(w, config, true)
650 }
651
652
653
654
655
656
657 func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) {
658 return e.serializePrivate(w, config, false)
659 }
660
661 func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) {
662 if e.PrivateKey == nil {
663 return goerrors.New("openpgp: private key is missing")
664 }
665 err = e.PrivateKey.Serialize(w)
666 if err != nil {
667 return
668 }
669 for _, revocation := range e.Revocations {
670 err := revocation.Serialize(w)
671 if err != nil {
672 return err
673 }
674 }
675 for _, ident := range e.Identities {
676 err = ident.UserId.Serialize(w)
677 if err != nil {
678 return
679 }
680 if reSign {
681 if ident.SelfSignature == nil {
682 return goerrors.New("openpgp: can't re-sign identity without valid self-signature")
683 }
684 err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
685 if err != nil {
686 return
687 }
688 }
689 for _, sig := range ident.Signatures {
690 err = sig.Serialize(w)
691 if err != nil {
692 return err
693 }
694 }
695 }
696 for _, subkey := range e.Subkeys {
697 err = subkey.PrivateKey.Serialize(w)
698 if err != nil {
699 return
700 }
701 if reSign {
702 err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
703 if err != nil {
704 return
705 }
706 if subkey.Sig.EmbeddedSignature != nil {
707 err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey,
708 subkey.PrivateKey, config)
709 if err != nil {
710 return
711 }
712 }
713 }
714 for _, revocation := range subkey.Revocations {
715 err := revocation.Serialize(w)
716 if err != nil {
717 return err
718 }
719 }
720 err = subkey.Sig.Serialize(w)
721 if err != nil {
722 return
723 }
724 }
725 return nil
726 }
727
728
729
730 func (e *Entity) Serialize(w io.Writer) error {
731 err := e.PrimaryKey.Serialize(w)
732 if err != nil {
733 return err
734 }
735 for _, revocation := range e.Revocations {
736 err := revocation.Serialize(w)
737 if err != nil {
738 return err
739 }
740 }
741 for _, ident := range e.Identities {
742 err = ident.UserId.Serialize(w)
743 if err != nil {
744 return err
745 }
746 for _, sig := range ident.Signatures {
747 err = sig.Serialize(w)
748 if err != nil {
749 return err
750 }
751 }
752 }
753 for _, subkey := range e.Subkeys {
754 err = subkey.PublicKey.Serialize(w)
755 if err != nil {
756 return err
757 }
758 for _, revocation := range subkey.Revocations {
759 err := revocation.Serialize(w)
760 if err != nil {
761 return err
762 }
763 }
764 err = subkey.Sig.Serialize(w)
765 if err != nil {
766 return err
767 }
768 }
769 return nil
770 }
771
772
773
774
775
776
777 func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
778 certificationKey, ok := signer.CertificationKey(config.Now())
779 if !ok {
780 return errors.InvalidArgumentError("no valid certification key found")
781 }
782
783 if certificationKey.PrivateKey.Encrypted {
784 return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
785 }
786
787 ident, ok := e.Identities[identity]
788 if !ok {
789 return errors.InvalidArgumentError("given identity string not found in Entity")
790 }
791
792 sig := createSignaturePacket(certificationKey.PublicKey, packet.SigTypeGenericCert, config)
793
794 signingUserID := config.SigningUserId()
795 if signingUserID != "" {
796 if _, ok := signer.Identities[signingUserID]; !ok {
797 return errors.InvalidArgumentError("signer identity string not found in signer Entity")
798 }
799 sig.SignerUserId = &signingUserID
800 }
801
802 if err := sig.SignUserId(identity, e.PrimaryKey, certificationKey.PrivateKey, config); err != nil {
803 return err
804 }
805 ident.Signatures = append(ident.Signatures, sig)
806 return nil
807 }
808
809
810
811
812 func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
813 revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeKeyRevocation, config)
814 revSig.RevocationReason = &reason
815 revSig.RevocationReasonText = reasonText
816
817 if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil {
818 return err
819 }
820 e.Revocations = append(e.Revocations, revSig)
821 return nil
822 }
823
824
825
826
827 func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
828 if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil {
829 return errors.InvalidArgumentError("given subkey is not associated with this key")
830 }
831
832 revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyRevocation, config)
833 revSig.RevocationReason = &reason
834 revSig.RevocationReasonText = reasonText
835
836 if err := revSig.RevokeSubkey(sk.PublicKey, e.PrivateKey, config); err != nil {
837 return err
838 }
839
840 sk.Revocations = append(sk.Revocations, revSig)
841 return nil
842 }
843
View as plain text