OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / openpgp / packet / signature.go
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 packet
6
7 import (
8         "bytes"
9         "crypto"
10         "crypto/dsa"
11         "crypto/ecdsa"
12         "encoding/asn1"
13         "encoding/binary"
14         "hash"
15         "io"
16         "math/big"
17         "strconv"
18         "time"
19
20         "golang.org/x/crypto/openpgp/errors"
21         "golang.org/x/crypto/openpgp/s2k"
22 )
23
24 const (
25         // See RFC 4880, section 5.2.3.21 for details.
26         KeyFlagCertify = 1 << iota
27         KeyFlagSign
28         KeyFlagEncryptCommunications
29         KeyFlagEncryptStorage
30 )
31
32 // Signature represents a signature. See RFC 4880, section 5.2.
33 type Signature struct {
34         SigType    SignatureType
35         PubKeyAlgo PublicKeyAlgorithm
36         Hash       crypto.Hash
37
38         // HashSuffix is extra data that is hashed in after the signed data.
39         HashSuffix []byte
40         // HashTag contains the first two bytes of the hash for fast rejection
41         // of bad signed data.
42         HashTag      [2]byte
43         CreationTime time.Time
44
45         RSASignature         parsedMPI
46         DSASigR, DSASigS     parsedMPI
47         ECDSASigR, ECDSASigS parsedMPI
48
49         // rawSubpackets contains the unparsed subpackets, in order.
50         rawSubpackets []outputSubpacket
51
52         // The following are optional so are nil when not included in the
53         // signature.
54
55         SigLifetimeSecs, KeyLifetimeSecs                        *uint32
56         PreferredSymmetric, PreferredHash, PreferredCompression []uint8
57         IssuerKeyId                                             *uint64
58         IsPrimaryId                                             *bool
59
60         // FlagsValid is set if any flags were given. See RFC 4880, section
61         // 5.2.3.21 for details.
62         FlagsValid                                                           bool
63         FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
64
65         // RevocationReason is set if this signature has been revoked.
66         // See RFC 4880, section 5.2.3.23 for details.
67         RevocationReason     *uint8
68         RevocationReasonText string
69
70         // MDC is set if this signature has a feature packet that indicates
71         // support for MDC subpackets.
72         MDC bool
73
74         // EmbeddedSignature, if non-nil, is a signature of the parent key, by
75         // this key. This prevents an attacker from claiming another's signing
76         // subkey as their own.
77         EmbeddedSignature *Signature
78
79         outSubpackets []outputSubpacket
80 }
81
82 func (sig *Signature) parse(r io.Reader) (err error) {
83         // RFC 4880, section 5.2.3
84         var buf [5]byte
85         _, err = readFull(r, buf[:1])
86         if err != nil {
87                 return
88         }
89         if buf[0] != 4 {
90                 err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
91                 return
92         }
93
94         _, err = readFull(r, buf[:5])
95         if err != nil {
96                 return
97         }
98         sig.SigType = SignatureType(buf[0])
99         sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
100         switch sig.PubKeyAlgo {
101         case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
102         default:
103                 err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
104                 return
105         }
106
107         var ok bool
108         sig.Hash, ok = s2k.HashIdToHash(buf[2])
109         if !ok {
110                 return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
111         }
112
113         hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
114         l := 6 + hashedSubpacketsLength
115         sig.HashSuffix = make([]byte, l+6)
116         sig.HashSuffix[0] = 4
117         copy(sig.HashSuffix[1:], buf[:5])
118         hashedSubpackets := sig.HashSuffix[6:l]
119         _, err = readFull(r, hashedSubpackets)
120         if err != nil {
121                 return
122         }
123         // See RFC 4880, section 5.2.4
124         trailer := sig.HashSuffix[l:]
125         trailer[0] = 4
126         trailer[1] = 0xff
127         trailer[2] = uint8(l >> 24)
128         trailer[3] = uint8(l >> 16)
129         trailer[4] = uint8(l >> 8)
130         trailer[5] = uint8(l)
131
132         err = parseSignatureSubpackets(sig, hashedSubpackets, true)
133         if err != nil {
134                 return
135         }
136
137         _, err = readFull(r, buf[:2])
138         if err != nil {
139                 return
140         }
141         unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
142         unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
143         _, err = readFull(r, unhashedSubpackets)
144         if err != nil {
145                 return
146         }
147         err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
148         if err != nil {
149                 return
150         }
151
152         _, err = readFull(r, sig.HashTag[:2])
153         if err != nil {
154                 return
155         }
156
157         switch sig.PubKeyAlgo {
158         case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
159                 sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
160         case PubKeyAlgoDSA:
161                 sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
162                 if err == nil {
163                         sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
164                 }
165         case PubKeyAlgoECDSA:
166                 sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
167                 if err == nil {
168                         sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
169                 }
170         default:
171                 panic("unreachable")
172         }
173         return
174 }
175
176 // parseSignatureSubpackets parses subpackets of the main signature packet. See
177 // RFC 4880, section 5.2.3.1.
178 func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
179         for len(subpackets) > 0 {
180                 subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
181                 if err != nil {
182                         return
183                 }
184         }
185
186         if sig.CreationTime.IsZero() {
187                 err = errors.StructuralError("no creation time in signature")
188         }
189
190         return
191 }
192
193 type signatureSubpacketType uint8
194
195 const (
196         creationTimeSubpacket        signatureSubpacketType = 2
197         signatureExpirationSubpacket signatureSubpacketType = 3
198         keyExpirationSubpacket       signatureSubpacketType = 9
199         prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
200         issuerSubpacket              signatureSubpacketType = 16
201         prefHashAlgosSubpacket       signatureSubpacketType = 21
202         prefCompressionSubpacket     signatureSubpacketType = 22
203         primaryUserIdSubpacket       signatureSubpacketType = 25
204         keyFlagsSubpacket            signatureSubpacketType = 27
205         reasonForRevocationSubpacket signatureSubpacketType = 29
206         featuresSubpacket            signatureSubpacketType = 30
207         embeddedSignatureSubpacket   signatureSubpacketType = 32
208 )
209
210 // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
211 func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
212         // RFC 4880, section 5.2.3.1
213         var (
214                 length     uint32
215                 packetType signatureSubpacketType
216                 isCritical bool
217         )
218         switch {
219         case subpacket[0] < 192:
220                 length = uint32(subpacket[0])
221                 subpacket = subpacket[1:]
222         case subpacket[0] < 255:
223                 if len(subpacket) < 2 {
224                         goto Truncated
225                 }
226                 length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
227                 subpacket = subpacket[2:]
228         default:
229                 if len(subpacket) < 5 {
230                         goto Truncated
231                 }
232                 length = uint32(subpacket[1])<<24 |
233                         uint32(subpacket[2])<<16 |
234                         uint32(subpacket[3])<<8 |
235                         uint32(subpacket[4])
236                 subpacket = subpacket[5:]
237         }
238         if length > uint32(len(subpacket)) {
239                 goto Truncated
240         }
241         rest = subpacket[length:]
242         subpacket = subpacket[:length]
243         if len(subpacket) == 0 {
244                 err = errors.StructuralError("zero length signature subpacket")
245                 return
246         }
247         packetType = signatureSubpacketType(subpacket[0] & 0x7f)
248         isCritical = subpacket[0]&0x80 == 0x80
249         subpacket = subpacket[1:]
250         sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
251         switch packetType {
252         case creationTimeSubpacket:
253                 if !isHashed {
254                         err = errors.StructuralError("signature creation time in non-hashed area")
255                         return
256                 }
257                 if len(subpacket) != 4 {
258                         err = errors.StructuralError("signature creation time not four bytes")
259                         return
260                 }
261                 t := binary.BigEndian.Uint32(subpacket)
262                 sig.CreationTime = time.Unix(int64(t), 0)
263         case signatureExpirationSubpacket:
264                 // Signature expiration time, section 5.2.3.10
265                 if !isHashed {
266                         return
267                 }
268                 if len(subpacket) != 4 {
269                         err = errors.StructuralError("expiration subpacket with bad length")
270                         return
271                 }
272                 sig.SigLifetimeSecs = new(uint32)
273                 *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
274         case keyExpirationSubpacket:
275                 // Key expiration time, section 5.2.3.6
276                 if !isHashed {
277                         return
278                 }
279                 if len(subpacket) != 4 {
280                         err = errors.StructuralError("key expiration subpacket with bad length")
281                         return
282                 }
283                 sig.KeyLifetimeSecs = new(uint32)
284                 *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
285         case prefSymmetricAlgosSubpacket:
286                 // Preferred symmetric algorithms, section 5.2.3.7
287                 if !isHashed {
288                         return
289                 }
290                 sig.PreferredSymmetric = make([]byte, len(subpacket))
291                 copy(sig.PreferredSymmetric, subpacket)
292         case issuerSubpacket:
293                 // Issuer, section 5.2.3.5
294                 if len(subpacket) != 8 {
295                         err = errors.StructuralError("issuer subpacket with bad length")
296                         return
297                 }
298                 sig.IssuerKeyId = new(uint64)
299                 *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
300         case prefHashAlgosSubpacket:
301                 // Preferred hash algorithms, section 5.2.3.8
302                 if !isHashed {
303                         return
304                 }
305                 sig.PreferredHash = make([]byte, len(subpacket))
306                 copy(sig.PreferredHash, subpacket)
307         case prefCompressionSubpacket:
308                 // Preferred compression algorithms, section 5.2.3.9
309                 if !isHashed {
310                         return
311                 }
312                 sig.PreferredCompression = make([]byte, len(subpacket))
313                 copy(sig.PreferredCompression, subpacket)
314         case primaryUserIdSubpacket:
315                 // Primary User ID, section 5.2.3.19
316                 if !isHashed {
317                         return
318                 }
319                 if len(subpacket) != 1 {
320                         err = errors.StructuralError("primary user id subpacket with bad length")
321                         return
322                 }
323                 sig.IsPrimaryId = new(bool)
324                 if subpacket[0] > 0 {
325                         *sig.IsPrimaryId = true
326                 }
327         case keyFlagsSubpacket:
328                 // Key flags, section 5.2.3.21
329                 if !isHashed {
330                         return
331                 }
332                 if len(subpacket) == 0 {
333                         err = errors.StructuralError("empty key flags subpacket")
334                         return
335                 }
336                 sig.FlagsValid = true
337                 if subpacket[0]&KeyFlagCertify != 0 {
338                         sig.FlagCertify = true
339                 }
340                 if subpacket[0]&KeyFlagSign != 0 {
341                         sig.FlagSign = true
342                 }
343                 if subpacket[0]&KeyFlagEncryptCommunications != 0 {
344                         sig.FlagEncryptCommunications = true
345                 }
346                 if subpacket[0]&KeyFlagEncryptStorage != 0 {
347                         sig.FlagEncryptStorage = true
348                 }
349         case reasonForRevocationSubpacket:
350                 // Reason For Revocation, section 5.2.3.23
351                 if !isHashed {
352                         return
353                 }
354                 if len(subpacket) == 0 {
355                         err = errors.StructuralError("empty revocation reason subpacket")
356                         return
357                 }
358                 sig.RevocationReason = new(uint8)
359                 *sig.RevocationReason = subpacket[0]
360                 sig.RevocationReasonText = string(subpacket[1:])
361         case featuresSubpacket:
362                 // Features subpacket, section 5.2.3.24 specifies a very general
363                 // mechanism for OpenPGP implementations to signal support for new
364                 // features. In practice, the subpacket is used exclusively to
365                 // indicate support for MDC-protected encryption.
366                 sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
367         case embeddedSignatureSubpacket:
368                 // Only usage is in signatures that cross-certify
369                 // signing subkeys. section 5.2.3.26 describes the
370                 // format, with its usage described in section 11.1
371                 if sig.EmbeddedSignature != nil {
372                         err = errors.StructuralError("Cannot have multiple embedded signatures")
373                         return
374                 }
375                 sig.EmbeddedSignature = new(Signature)
376                 // Embedded signatures are required to be v4 signatures see
377                 // section 12.1. However, we only parse v4 signatures in this
378                 // file anyway.
379                 if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
380                         return nil, err
381                 }
382                 if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
383                         return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
384                 }
385         default:
386                 if isCritical {
387                         err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
388                         return
389                 }
390         }
391         return
392
393 Truncated:
394         err = errors.StructuralError("signature subpacket truncated")
395         return
396 }
397
398 // subpacketLengthLength returns the length, in bytes, of an encoded length value.
399 func subpacketLengthLength(length int) int {
400         if length < 192 {
401                 return 1
402         }
403         if length < 16320 {
404                 return 2
405         }
406         return 5
407 }
408
409 // serializeSubpacketLength marshals the given length into to.
410 func serializeSubpacketLength(to []byte, length int) int {
411         // RFC 4880, Section 4.2.2.
412         if length < 192 {
413                 to[0] = byte(length)
414                 return 1
415         }
416         if length < 16320 {
417                 length -= 192
418                 to[0] = byte((length >> 8) + 192)
419                 to[1] = byte(length)
420                 return 2
421         }
422         to[0] = 255
423         to[1] = byte(length >> 24)
424         to[2] = byte(length >> 16)
425         to[3] = byte(length >> 8)
426         to[4] = byte(length)
427         return 5
428 }
429
430 // subpacketsLength returns the serialized length, in bytes, of the given
431 // subpackets.
432 func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
433         for _, subpacket := range subpackets {
434                 if subpacket.hashed == hashed {
435                         length += subpacketLengthLength(len(subpacket.contents) + 1)
436                         length += 1 // type byte
437                         length += len(subpacket.contents)
438                 }
439         }
440         return
441 }
442
443 // serializeSubpackets marshals the given subpackets into to.
444 func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
445         for _, subpacket := range subpackets {
446                 if subpacket.hashed == hashed {
447                         n := serializeSubpacketLength(to, len(subpacket.contents)+1)
448                         to[n] = byte(subpacket.subpacketType)
449                         to = to[1+n:]
450                         n = copy(to, subpacket.contents)
451                         to = to[n:]
452                 }
453         }
454         return
455 }
456
457 // KeyExpired returns whether sig is a self-signature of a key that has
458 // expired.
459 func (sig *Signature) KeyExpired(currentTime time.Time) bool {
460         if sig.KeyLifetimeSecs == nil {
461                 return false
462         }
463         expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
464         return currentTime.After(expiry)
465 }
466
467 // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
468 func (sig *Signature) buildHashSuffix() (err error) {
469         hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
470
471         var ok bool
472         l := 6 + hashedSubpacketsLen
473         sig.HashSuffix = make([]byte, l+6)
474         sig.HashSuffix[0] = 4
475         sig.HashSuffix[1] = uint8(sig.SigType)
476         sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
477         sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
478         if !ok {
479                 sig.HashSuffix = nil
480                 return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
481         }
482         sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
483         sig.HashSuffix[5] = byte(hashedSubpacketsLen)
484         serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
485         trailer := sig.HashSuffix[l:]
486         trailer[0] = 4
487         trailer[1] = 0xff
488         trailer[2] = byte(l >> 24)
489         trailer[3] = byte(l >> 16)
490         trailer[4] = byte(l >> 8)
491         trailer[5] = byte(l)
492         return
493 }
494
495 func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
496         err = sig.buildHashSuffix()
497         if err != nil {
498                 return
499         }
500
501         h.Write(sig.HashSuffix)
502         digest = h.Sum(nil)
503         copy(sig.HashTag[:], digest)
504         return
505 }
506
507 // Sign signs a message with a private key. The hash, h, must contain
508 // the hash of the message to be signed and will be mutated by this function.
509 // On success, the signature is stored in sig. Call Serialize to write it out.
510 // If config is nil, sensible defaults will be used.
511 func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
512         sig.outSubpackets = sig.buildSubpackets()
513         digest, err := sig.signPrepareHash(h)
514         if err != nil {
515                 return
516         }
517
518         switch priv.PubKeyAlgo {
519         case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
520                 // supports both *rsa.PrivateKey and crypto.Signer
521                 sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
522                 sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
523         case PubKeyAlgoDSA:
524                 dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
525
526                 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
527                 subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
528                 if len(digest) > subgroupSize {
529                         digest = digest[:subgroupSize]
530                 }
531                 r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
532                 if err == nil {
533                         sig.DSASigR.bytes = r.Bytes()
534                         sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
535                         sig.DSASigS.bytes = s.Bytes()
536                         sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
537                 }
538         case PubKeyAlgoECDSA:
539                 var r, s *big.Int
540                 if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
541                         // direct support, avoid asn1 wrapping/unwrapping
542                         r, s, err = ecdsa.Sign(config.Random(), pk, digest)
543                 } else {
544                         var b []byte
545                         b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil)
546                         if err == nil {
547                                 r, s, err = unwrapECDSASig(b)
548                         }
549                 }
550                 if err == nil {
551                         sig.ECDSASigR = fromBig(r)
552                         sig.ECDSASigS = fromBig(s)
553                 }
554         default:
555                 err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
556         }
557
558         return
559 }
560
561 // unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
562 // signature.
563 func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
564         var ecsdaSig struct {
565                 R, S *big.Int
566         }
567         _, err = asn1.Unmarshal(b, &ecsdaSig)
568         if err != nil {
569                 return
570         }
571         return ecsdaSig.R, ecsdaSig.S, nil
572 }
573
574 // SignUserId computes a signature from priv, asserting that pub is a valid
575 // key for the identity id.  On success, the signature is stored in sig. Call
576 // Serialize to write it out.
577 // If config is nil, sensible defaults will be used.
578 func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
579         h, err := userIdSignatureHash(id, pub, sig.Hash)
580         if err != nil {
581                 return err
582         }
583         return sig.Sign(h, priv, config)
584 }
585
586 // SignKey computes a signature from priv, asserting that pub is a subkey. On
587 // success, the signature is stored in sig. Call Serialize to write it out.
588 // If config is nil, sensible defaults will be used.
589 func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
590         h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
591         if err != nil {
592                 return err
593         }
594         return sig.Sign(h, priv, config)
595 }
596
597 // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
598 // called first.
599 func (sig *Signature) Serialize(w io.Writer) (err error) {
600         if len(sig.outSubpackets) == 0 {
601                 sig.outSubpackets = sig.rawSubpackets
602         }
603         if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
604                 return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
605         }
606
607         sigLength := 0
608         switch sig.PubKeyAlgo {
609         case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
610                 sigLength = 2 + len(sig.RSASignature.bytes)
611         case PubKeyAlgoDSA:
612                 sigLength = 2 + len(sig.DSASigR.bytes)
613                 sigLength += 2 + len(sig.DSASigS.bytes)
614         case PubKeyAlgoECDSA:
615                 sigLength = 2 + len(sig.ECDSASigR.bytes)
616                 sigLength += 2 + len(sig.ECDSASigS.bytes)
617         default:
618                 panic("impossible")
619         }
620
621         unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
622         length := len(sig.HashSuffix) - 6 /* trailer not included */ +
623                 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
624                 2 /* hash tag */ + sigLength
625         err = serializeHeader(w, packetTypeSignature, length)
626         if err != nil {
627                 return
628         }
629
630         _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
631         if err != nil {
632                 return
633         }
634
635         unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
636         unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
637         unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
638         serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
639
640         _, err = w.Write(unhashedSubpackets)
641         if err != nil {
642                 return
643         }
644         _, err = w.Write(sig.HashTag[:])
645         if err != nil {
646                 return
647         }
648
649         switch sig.PubKeyAlgo {
650         case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
651                 err = writeMPIs(w, sig.RSASignature)
652         case PubKeyAlgoDSA:
653                 err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
654         case PubKeyAlgoECDSA:
655                 err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
656         default:
657                 panic("impossible")
658         }
659         return
660 }
661
662 // outputSubpacket represents a subpacket to be marshaled.
663 type outputSubpacket struct {
664         hashed        bool // true if this subpacket is in the hashed area.
665         subpacketType signatureSubpacketType
666         isCritical    bool
667         contents      []byte
668 }
669
670 func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
671         creationTime := make([]byte, 4)
672         binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
673         subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
674
675         if sig.IssuerKeyId != nil {
676                 keyId := make([]byte, 8)
677                 binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
678                 subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
679         }
680
681         if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
682                 sigLifetime := make([]byte, 4)
683                 binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
684                 subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
685         }
686
687         // Key flags may only appear in self-signatures or certification signatures.
688
689         if sig.FlagsValid {
690                 var flags byte
691                 if sig.FlagCertify {
692                         flags |= KeyFlagCertify
693                 }
694                 if sig.FlagSign {
695                         flags |= KeyFlagSign
696                 }
697                 if sig.FlagEncryptCommunications {
698                         flags |= KeyFlagEncryptCommunications
699                 }
700                 if sig.FlagEncryptStorage {
701                         flags |= KeyFlagEncryptStorage
702                 }
703                 subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
704         }
705
706         // The following subpackets may only appear in self-signatures
707
708         if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
709                 keyLifetime := make([]byte, 4)
710                 binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
711                 subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
712         }
713
714         if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
715                 subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
716         }
717
718         if len(sig.PreferredSymmetric) > 0 {
719                 subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
720         }
721
722         if len(sig.PreferredHash) > 0 {
723                 subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
724         }
725
726         if len(sig.PreferredCompression) > 0 {
727                 subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
728         }
729
730         return
731 }