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 5package packet 6 7import ( 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 24const ( 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. 33type 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 82func (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. 178func 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 193type signatureSubpacketType uint8 194 195const ( 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. 211func 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 393Truncated: 394 err = errors.StructuralError("signature subpacket truncated") 395 return 396} 397 398// subpacketLengthLength returns the length, in bytes, of an encoded length value. 399func 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. 410func 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. 432func 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. 444func 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. 459func (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. 468func (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 495func (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. 511func (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. 563func 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. 578func (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. 589func (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. 599func (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. 663type 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 670func (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} 732