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