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