]>
Commit | Line | Data |
---|---|---|
c680a8e1 RS |
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 | ||
5 | package openpgp | |
6 | ||
7 | import ( | |
8 | "crypto/rsa" | |
9 | "io" | |
10 | "time" | |
11 | ||
12 | "golang.org/x/crypto/openpgp/armor" | |
13 | "golang.org/x/crypto/openpgp/errors" | |
14 | "golang.org/x/crypto/openpgp/packet" | |
15 | ) | |
16 | ||
17 | // PublicKeyType is the armor type for a PGP public key. | |
18 | var PublicKeyType = "PGP PUBLIC KEY BLOCK" | |
19 | ||
20 | // PrivateKeyType is the armor type for a PGP private key. | |
21 | var 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. | |
26 | type 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. | |
36 | type 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 | Signatures []*packet.Signature | |
41 | } | |
42 | ||
43 | // A Subkey is an additional public key in an Entity. Subkeys can be used for | |
44 | // encryption. | |
45 | type Subkey struct { | |
46 | PublicKey *packet.PublicKey | |
47 | PrivateKey *packet.PrivateKey | |
48 | Sig *packet.Signature | |
49 | } | |
50 | ||
51 | // A Key identifies a specific public key in an Entity. This is either the | |
52 | // Entity's primary key or a subkey. | |
53 | type Key struct { | |
54 | Entity *Entity | |
55 | PublicKey *packet.PublicKey | |
56 | PrivateKey *packet.PrivateKey | |
57 | SelfSignature *packet.Signature | |
58 | } | |
59 | ||
60 | // A KeyRing provides access to public and private keys. | |
61 | type KeyRing interface { | |
62 | // KeysById returns the set of keys that have the given key id. | |
63 | KeysById(id uint64) []Key | |
64 | // KeysByIdAndUsage returns the set of keys with the given id | |
65 | // that also meet the key usage given by requiredUsage. | |
66 | // The requiredUsage is expressed as the bitwise-OR of | |
67 | // packet.KeyFlag* values. | |
68 | KeysByIdUsage(id uint64, requiredUsage byte) []Key | |
69 | // DecryptionKeys returns all private keys that are valid for | |
70 | // decryption. | |
71 | DecryptionKeys() []Key | |
72 | } | |
73 | ||
74 | // primaryIdentity returns the Identity marked as primary or the first identity | |
75 | // if none are so marked. | |
76 | func (e *Entity) primaryIdentity() *Identity { | |
77 | var firstIdentity *Identity | |
78 | for _, ident := range e.Identities { | |
79 | if firstIdentity == nil { | |
80 | firstIdentity = ident | |
81 | } | |
82 | if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { | |
83 | return ident | |
84 | } | |
85 | } | |
86 | return firstIdentity | |
87 | } | |
88 | ||
89 | // encryptionKey returns the best candidate Key for encrypting a message to the | |
90 | // given Entity. | |
91 | func (e *Entity) encryptionKey(now time.Time) (Key, bool) { | |
92 | candidateSubkey := -1 | |
93 | ||
94 | // Iterate the keys to find the newest key | |
95 | var maxTime time.Time | |
96 | for i, subkey := range e.Subkeys { | |
97 | if subkey.Sig.FlagsValid && | |
98 | subkey.Sig.FlagEncryptCommunications && | |
99 | subkey.PublicKey.PubKeyAlgo.CanEncrypt() && | |
100 | !subkey.Sig.KeyExpired(now) && | |
101 | (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { | |
102 | candidateSubkey = i | |
103 | maxTime = subkey.Sig.CreationTime | |
104 | } | |
105 | } | |
106 | ||
107 | if candidateSubkey != -1 { | |
108 | subkey := e.Subkeys[candidateSubkey] | |
109 | return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true | |
110 | } | |
111 | ||
112 | // If we don't have any candidate subkeys for encryption and | |
113 | // the primary key doesn't have any usage metadata then we | |
114 | // assume that the primary key is ok. Or, if the primary key is | |
115 | // marked as ok to encrypt to, then we can obviously use it. | |
116 | i := e.primaryIdentity() | |
117 | if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && | |
118 | e.PrimaryKey.PubKeyAlgo.CanEncrypt() && | |
119 | !i.SelfSignature.KeyExpired(now) { | |
120 | return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true | |
121 | } | |
122 | ||
123 | // This Entity appears to be signing only. | |
124 | return Key{}, false | |
125 | } | |
126 | ||
127 | // signingKey return the best candidate Key for signing a message with this | |
128 | // Entity. | |
129 | func (e *Entity) signingKey(now time.Time) (Key, bool) { | |
130 | candidateSubkey := -1 | |
131 | ||
132 | for i, subkey := range e.Subkeys { | |
133 | if subkey.Sig.FlagsValid && | |
134 | subkey.Sig.FlagSign && | |
135 | subkey.PublicKey.PubKeyAlgo.CanSign() && | |
136 | !subkey.Sig.KeyExpired(now) { | |
137 | candidateSubkey = i | |
138 | break | |
139 | } | |
140 | } | |
141 | ||
142 | if candidateSubkey != -1 { | |
143 | subkey := e.Subkeys[candidateSubkey] | |
144 | return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true | |
145 | } | |
146 | ||
147 | // If we have no candidate subkey then we assume that it's ok to sign | |
148 | // with the primary key. | |
149 | i := e.primaryIdentity() | |
150 | if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && | |
151 | !i.SelfSignature.KeyExpired(now) { | |
152 | return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true | |
153 | } | |
154 | ||
155 | return Key{}, false | |
156 | } | |
157 | ||
158 | // An EntityList contains one or more Entities. | |
159 | type EntityList []*Entity | |
160 | ||
161 | // KeysById returns the set of keys that have the given key id. | |
162 | func (el EntityList) KeysById(id uint64) (keys []Key) { | |
163 | for _, e := range el { | |
164 | if e.PrimaryKey.KeyId == id { | |
165 | var selfSig *packet.Signature | |
166 | for _, ident := range e.Identities { | |
167 | if selfSig == nil { | |
168 | selfSig = ident.SelfSignature | |
169 | } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { | |
170 | selfSig = ident.SelfSignature | |
171 | break | |
172 | } | |
173 | } | |
174 | keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) | |
175 | } | |
176 | ||
177 | for _, subKey := range e.Subkeys { | |
178 | if subKey.PublicKey.KeyId == id { | |
179 | keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) | |
180 | } | |
181 | } | |
182 | } | |
183 | return | |
184 | } | |
185 | ||
186 | // KeysByIdAndUsage returns the set of keys with the given id that also meet | |
187 | // the key usage given by requiredUsage. The requiredUsage is expressed as | |
188 | // the bitwise-OR of packet.KeyFlag* values. | |
189 | func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { | |
190 | for _, key := range el.KeysById(id) { | |
191 | if len(key.Entity.Revocations) > 0 { | |
192 | continue | |
193 | } | |
194 | ||
195 | if key.SelfSignature.RevocationReason != nil { | |
196 | continue | |
197 | } | |
198 | ||
199 | if key.SelfSignature.FlagsValid && requiredUsage != 0 { | |
200 | var usage byte | |
201 | if key.SelfSignature.FlagCertify { | |
202 | usage |= packet.KeyFlagCertify | |
203 | } | |
204 | if key.SelfSignature.FlagSign { | |
205 | usage |= packet.KeyFlagSign | |
206 | } | |
207 | if key.SelfSignature.FlagEncryptCommunications { | |
208 | usage |= packet.KeyFlagEncryptCommunications | |
209 | } | |
210 | if key.SelfSignature.FlagEncryptStorage { | |
211 | usage |= packet.KeyFlagEncryptStorage | |
212 | } | |
213 | if usage&requiredUsage != requiredUsage { | |
214 | continue | |
215 | } | |
216 | } | |
217 | ||
218 | keys = append(keys, key) | |
219 | } | |
220 | return | |
221 | } | |
222 | ||
223 | // DecryptionKeys returns all private keys that are valid for decryption. | |
224 | func (el EntityList) DecryptionKeys() (keys []Key) { | |
225 | for _, e := range el { | |
226 | for _, subKey := range e.Subkeys { | |
227 | if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { | |
228 | keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) | |
229 | } | |
230 | } | |
231 | } | |
232 | return | |
233 | } | |
234 | ||
235 | // ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. | |
236 | func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { | |
237 | block, err := armor.Decode(r) | |
238 | if err == io.EOF { | |
239 | return nil, errors.InvalidArgumentError("no armored data found") | |
240 | } | |
241 | if err != nil { | |
242 | return nil, err | |
243 | } | |
244 | if block.Type != PublicKeyType && block.Type != PrivateKeyType { | |
245 | return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) | |
246 | } | |
247 | ||
248 | return ReadKeyRing(block.Body) | |
249 | } | |
250 | ||
251 | // ReadKeyRing reads one or more public/private keys. Unsupported keys are | |
252 | // ignored as long as at least a single valid key is found. | |
253 | func ReadKeyRing(r io.Reader) (el EntityList, err error) { | |
254 | packets := packet.NewReader(r) | |
255 | var lastUnsupportedError error | |
256 | ||
257 | for { | |
258 | var e *Entity | |
259 | e, err = ReadEntity(packets) | |
260 | if err != nil { | |
261 | // TODO: warn about skipped unsupported/unreadable keys | |
262 | if _, ok := err.(errors.UnsupportedError); ok { | |
263 | lastUnsupportedError = err | |
264 | err = readToNextPublicKey(packets) | |
265 | } else if _, ok := err.(errors.StructuralError); ok { | |
266 | // Skip unreadable, badly-formatted keys | |
267 | lastUnsupportedError = err | |
268 | err = readToNextPublicKey(packets) | |
269 | } | |
270 | if err == io.EOF { | |
271 | err = nil | |
272 | break | |
273 | } | |
274 | if err != nil { | |
275 | el = nil | |
276 | break | |
277 | } | |
278 | } else { | |
279 | el = append(el, e) | |
280 | } | |
281 | } | |
282 | ||
283 | if len(el) == 0 && err == nil { | |
284 | err = lastUnsupportedError | |
285 | } | |
286 | return | |
287 | } | |
288 | ||
289 | // readToNextPublicKey reads packets until the start of the entity and leaves | |
290 | // the first packet of the new entity in the Reader. | |
291 | func readToNextPublicKey(packets *packet.Reader) (err error) { | |
292 | var p packet.Packet | |
293 | for { | |
294 | p, err = packets.Next() | |
295 | if err == io.EOF { | |
296 | return | |
297 | } else if err != nil { | |
298 | if _, ok := err.(errors.UnsupportedError); ok { | |
299 | err = nil | |
300 | continue | |
301 | } | |
302 | return | |
303 | } | |
304 | ||
305 | if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { | |
306 | packets.Unread(p) | |
307 | return | |
308 | } | |
309 | } | |
310 | } | |
311 | ||
312 | // ReadEntity reads an entity (public key, identities, subkeys etc) from the | |
313 | // given Reader. | |
314 | func ReadEntity(packets *packet.Reader) (*Entity, error) { | |
315 | e := new(Entity) | |
316 | e.Identities = make(map[string]*Identity) | |
317 | ||
318 | p, err := packets.Next() | |
319 | if err != nil { | |
320 | return nil, err | |
321 | } | |
322 | ||
323 | var ok bool | |
324 | if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { | |
325 | if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { | |
326 | packets.Unread(p) | |
327 | return nil, errors.StructuralError("first packet was not a public/private key") | |
c680a8e1 | 328 | } |
15c0b25d | 329 | e.PrimaryKey = &e.PrivateKey.PublicKey |
c680a8e1 RS |
330 | } |
331 | ||
332 | if !e.PrimaryKey.PubKeyAlgo.CanSign() { | |
333 | return nil, errors.StructuralError("primary key cannot be used for signatures") | |
334 | } | |
335 | ||
c680a8e1 RS |
336 | var revocations []*packet.Signature |
337 | EachPacket: | |
338 | for { | |
339 | p, err := packets.Next() | |
340 | if err == io.EOF { | |
341 | break | |
342 | } else if err != nil { | |
343 | return nil, err | |
344 | } | |
345 | ||
346 | switch pkt := p.(type) { | |
347 | case *packet.UserId: | |
107c1cdb ND |
348 | if err := addUserID(e, packets, pkt); err != nil { |
349 | return nil, err | |
c680a8e1 RS |
350 | } |
351 | case *packet.Signature: | |
352 | if pkt.SigType == packet.SigTypeKeyRevocation { | |
353 | revocations = append(revocations, pkt) | |
354 | } else if pkt.SigType == packet.SigTypeDirectSignature { | |
355 | // TODO: RFC4880 5.2.1 permits signatures | |
356 | // directly on keys (eg. to bind additional | |
357 | // revocation keys). | |
c680a8e1 | 358 | } |
107c1cdb ND |
359 | // Else, ignoring the signature as it does not follow anything |
360 | // we would know to attach it to. | |
c680a8e1 RS |
361 | case *packet.PrivateKey: |
362 | if pkt.IsSubkey == false { | |
363 | packets.Unread(p) | |
364 | break EachPacket | |
365 | } | |
366 | err = addSubkey(e, packets, &pkt.PublicKey, pkt) | |
367 | if err != nil { | |
368 | return nil, err | |
369 | } | |
370 | case *packet.PublicKey: | |
371 | if pkt.IsSubkey == false { | |
372 | packets.Unread(p) | |
373 | break EachPacket | |
374 | } | |
375 | err = addSubkey(e, packets, pkt, nil) | |
376 | if err != nil { | |
377 | return nil, err | |
378 | } | |
379 | default: | |
380 | // we ignore unknown packets | |
381 | } | |
382 | } | |
383 | ||
384 | if len(e.Identities) == 0 { | |
385 | return nil, errors.StructuralError("entity without any identities") | |
386 | } | |
387 | ||
388 | for _, revocation := range revocations { | |
389 | err = e.PrimaryKey.VerifyRevocationSignature(revocation) | |
390 | if err == nil { | |
391 | e.Revocations = append(e.Revocations, revocation) | |
392 | } else { | |
393 | // TODO: RFC 4880 5.2.3.15 defines revocation keys. | |
394 | return nil, errors.StructuralError("revocation signature signed by alternate key") | |
395 | } | |
396 | } | |
397 | ||
398 | return e, nil | |
399 | } | |
400 | ||
107c1cdb ND |
401 | func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { |
402 | // Make a new Identity object, that we might wind up throwing away. | |
403 | // We'll only add it if we get a valid self-signature over this | |
404 | // userID. | |
405 | identity := new(Identity) | |
406 | identity.Name = pkt.Id | |
407 | identity.UserId = pkt | |
408 | ||
409 | for { | |
410 | p, err := packets.Next() | |
411 | if err == io.EOF { | |
412 | break | |
413 | } else if err != nil { | |
414 | return err | |
415 | } | |
416 | ||
417 | sig, ok := p.(*packet.Signature) | |
418 | if !ok { | |
419 | packets.Unread(p) | |
420 | break | |
421 | } | |
422 | ||
423 | if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { | |
424 | if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { | |
425 | return errors.StructuralError("user ID self-signature invalid: " + err.Error()) | |
426 | } | |
427 | identity.SelfSignature = sig | |
428 | e.Identities[pkt.Id] = identity | |
429 | } else { | |
430 | identity.Signatures = append(identity.Signatures, sig) | |
431 | } | |
432 | } | |
433 | ||
434 | return nil | |
435 | } | |
436 | ||
c680a8e1 RS |
437 | func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { |
438 | var subKey Subkey | |
439 | subKey.PublicKey = pub | |
440 | subKey.PrivateKey = priv | |
107c1cdb ND |
441 | |
442 | for { | |
443 | p, err := packets.Next() | |
444 | if err == io.EOF { | |
445 | break | |
446 | } else if err != nil { | |
447 | return errors.StructuralError("subkey signature invalid: " + err.Error()) | |
448 | } | |
449 | ||
450 | sig, ok := p.(*packet.Signature) | |
451 | if !ok { | |
452 | packets.Unread(p) | |
453 | break | |
454 | } | |
455 | ||
456 | if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation { | |
457 | return errors.StructuralError("subkey signature with wrong type") | |
458 | } | |
459 | ||
460 | if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil { | |
461 | return errors.StructuralError("subkey signature invalid: " + err.Error()) | |
462 | } | |
463 | ||
464 | switch sig.SigType { | |
465 | case packet.SigTypeSubkeyRevocation: | |
466 | subKey.Sig = sig | |
467 | case packet.SigTypeSubkeyBinding: | |
468 | ||
469 | if shouldReplaceSubkeySig(subKey.Sig, sig) { | |
470 | subKey.Sig = sig | |
471 | } | |
472 | } | |
c680a8e1 | 473 | } |
107c1cdb ND |
474 | |
475 | if subKey.Sig == nil { | |
c680a8e1 RS |
476 | return errors.StructuralError("subkey packet not followed by signature") |
477 | } | |
107c1cdb | 478 | |
c680a8e1 | 479 | e.Subkeys = append(e.Subkeys, subKey) |
107c1cdb | 480 | |
c680a8e1 RS |
481 | return nil |
482 | } | |
483 | ||
107c1cdb ND |
484 | func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool { |
485 | if potentialNewSig == nil { | |
486 | return false | |
487 | } | |
488 | ||
489 | if existingSig == nil { | |
490 | return true | |
491 | } | |
492 | ||
493 | if existingSig.SigType == packet.SigTypeSubkeyRevocation { | |
494 | return false // never override a revocation signature | |
495 | } | |
496 | ||
497 | return potentialNewSig.CreationTime.After(existingSig.CreationTime) | |
498 | } | |
499 | ||
c680a8e1 RS |
500 | const defaultRSAKeyBits = 2048 |
501 | ||
502 | // NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a | |
503 | // single identity composed of the given full name, comment and email, any of | |
504 | // which may be empty but must not contain any of "()<>\x00". | |
505 | // If config is nil, sensible defaults will be used. | |
506 | func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { | |
507 | currentTime := config.Now() | |
508 | ||
509 | bits := defaultRSAKeyBits | |
510 | if config != nil && config.RSABits != 0 { | |
511 | bits = config.RSABits | |
512 | } | |
513 | ||
514 | uid := packet.NewUserId(name, comment, email) | |
515 | if uid == nil { | |
516 | return nil, errors.InvalidArgumentError("user id field contained invalid characters") | |
517 | } | |
518 | signingPriv, err := rsa.GenerateKey(config.Random(), bits) | |
519 | if err != nil { | |
520 | return nil, err | |
521 | } | |
522 | encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) | |
523 | if err != nil { | |
524 | return nil, err | |
525 | } | |
526 | ||
527 | e := &Entity{ | |
528 | PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey), | |
529 | PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv), | |
530 | Identities: make(map[string]*Identity), | |
531 | } | |
532 | isPrimaryId := true | |
533 | e.Identities[uid.Id] = &Identity{ | |
107c1cdb | 534 | Name: uid.Id, |
c680a8e1 RS |
535 | UserId: uid, |
536 | SelfSignature: &packet.Signature{ | |
537 | CreationTime: currentTime, | |
538 | SigType: packet.SigTypePositiveCert, | |
539 | PubKeyAlgo: packet.PubKeyAlgoRSA, | |
540 | Hash: config.Hash(), | |
541 | IsPrimaryId: &isPrimaryId, | |
542 | FlagsValid: true, | |
543 | FlagSign: true, | |
544 | FlagCertify: true, | |
545 | IssuerKeyId: &e.PrimaryKey.KeyId, | |
546 | }, | |
547 | } | |
107c1cdb ND |
548 | err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) |
549 | if err != nil { | |
550 | return nil, err | |
551 | } | |
c680a8e1 RS |
552 | |
553 | // If the user passes in a DefaultHash via packet.Config, | |
554 | // set the PreferredHash for the SelfSignature. | |
555 | if config != nil && config.DefaultHash != 0 { | |
556 | e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} | |
557 | } | |
558 | ||
107c1cdb ND |
559 | // Likewise for DefaultCipher. |
560 | if config != nil && config.DefaultCipher != 0 { | |
561 | e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} | |
562 | } | |
563 | ||
c680a8e1 RS |
564 | e.Subkeys = make([]Subkey, 1) |
565 | e.Subkeys[0] = Subkey{ | |
566 | PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), | |
567 | PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv), | |
568 | Sig: &packet.Signature{ | |
569 | CreationTime: currentTime, | |
570 | SigType: packet.SigTypeSubkeyBinding, | |
571 | PubKeyAlgo: packet.PubKeyAlgoRSA, | |
572 | Hash: config.Hash(), | |
573 | FlagsValid: true, | |
574 | FlagEncryptStorage: true, | |
575 | FlagEncryptCommunications: true, | |
576 | IssuerKeyId: &e.PrimaryKey.KeyId, | |
577 | }, | |
578 | } | |
579 | e.Subkeys[0].PublicKey.IsSubkey = true | |
580 | e.Subkeys[0].PrivateKey.IsSubkey = true | |
107c1cdb ND |
581 | err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) |
582 | if err != nil { | |
583 | return nil, err | |
584 | } | |
c680a8e1 RS |
585 | return e, nil |
586 | } | |
587 | ||
107c1cdb ND |
588 | // SerializePrivate serializes an Entity, including private key material, but |
589 | // excluding signatures from other entities, to the given Writer. | |
590 | // Identities and subkeys are re-signed in case they changed since NewEntry. | |
c680a8e1 RS |
591 | // If config is nil, sensible defaults will be used. |
592 | func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { | |
593 | err = e.PrivateKey.Serialize(w) | |
594 | if err != nil { | |
595 | return | |
596 | } | |
597 | for _, ident := range e.Identities { | |
598 | err = ident.UserId.Serialize(w) | |
599 | if err != nil { | |
600 | return | |
601 | } | |
602 | err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) | |
603 | if err != nil { | |
604 | return | |
605 | } | |
606 | err = ident.SelfSignature.Serialize(w) | |
607 | if err != nil { | |
608 | return | |
609 | } | |
610 | } | |
611 | for _, subkey := range e.Subkeys { | |
612 | err = subkey.PrivateKey.Serialize(w) | |
613 | if err != nil { | |
614 | return | |
615 | } | |
616 | err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) | |
617 | if err != nil { | |
618 | return | |
619 | } | |
620 | err = subkey.Sig.Serialize(w) | |
621 | if err != nil { | |
622 | return | |
623 | } | |
624 | } | |
625 | return nil | |
626 | } | |
627 | ||
107c1cdb ND |
628 | // Serialize writes the public part of the given Entity to w, including |
629 | // signatures from other entities. No private key material will be output. | |
c680a8e1 RS |
630 | func (e *Entity) Serialize(w io.Writer) error { |
631 | err := e.PrimaryKey.Serialize(w) | |
632 | if err != nil { | |
633 | return err | |
634 | } | |
635 | for _, ident := range e.Identities { | |
636 | err = ident.UserId.Serialize(w) | |
637 | if err != nil { | |
638 | return err | |
639 | } | |
640 | err = ident.SelfSignature.Serialize(w) | |
641 | if err != nil { | |
642 | return err | |
643 | } | |
644 | for _, sig := range ident.Signatures { | |
645 | err = sig.Serialize(w) | |
646 | if err != nil { | |
647 | return err | |
648 | } | |
649 | } | |
650 | } | |
651 | for _, subkey := range e.Subkeys { | |
652 | err = subkey.PublicKey.Serialize(w) | |
653 | if err != nil { | |
654 | return err | |
655 | } | |
656 | err = subkey.Sig.Serialize(w) | |
657 | if err != nil { | |
658 | return err | |
659 | } | |
660 | } | |
661 | return nil | |
662 | } | |
663 | ||
664 | // SignIdentity adds a signature to e, from signer, attesting that identity is | |
665 | // associated with e. The provided identity must already be an element of | |
666 | // e.Identities and the private key of signer must have been decrypted if | |
667 | // necessary. | |
668 | // If config is nil, sensible defaults will be used. | |
669 | func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { | |
670 | if signer.PrivateKey == nil { | |
671 | return errors.InvalidArgumentError("signing Entity must have a private key") | |
672 | } | |
673 | if signer.PrivateKey.Encrypted { | |
674 | return errors.InvalidArgumentError("signing Entity's private key must be decrypted") | |
675 | } | |
676 | ident, ok := e.Identities[identity] | |
677 | if !ok { | |
678 | return errors.InvalidArgumentError("given identity string not found in Entity") | |
679 | } | |
680 | ||
681 | sig := &packet.Signature{ | |
682 | SigType: packet.SigTypeGenericCert, | |
683 | PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, | |
684 | Hash: config.Hash(), | |
685 | CreationTime: config.Now(), | |
686 | IssuerKeyId: &signer.PrivateKey.KeyId, | |
687 | } | |
688 | if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { | |
689 | return err | |
690 | } | |
691 | ident.Signatures = append(ident.Signatures, sig) | |
692 | return nil | |
693 | } |