signature.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  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. package packet
  5. import (
  6. "code.google.com/p/go.crypto/openpgp/errors"
  7. "code.google.com/p/go.crypto/openpgp/s2k"
  8. "crypto"
  9. "crypto/dsa"
  10. "crypto/rsa"
  11. "encoding/binary"
  12. "hash"
  13. "io"
  14. "strconv"
  15. "time"
  16. )
  17. // Signature represents a signature. See RFC 4880, section 5.2.
  18. type Signature struct {
  19. SigType SignatureType
  20. PubKeyAlgo PublicKeyAlgorithm
  21. Hash crypto.Hash
  22. // HashSuffix is extra data that is hashed in after the signed data.
  23. HashSuffix []byte
  24. // HashTag contains the first two bytes of the hash for fast rejection
  25. // of bad signed data.
  26. HashTag [2]byte
  27. CreationTime time.Time
  28. RSASignature parsedMPI
  29. DSASigR, DSASigS parsedMPI
  30. // rawSubpackets contains the unparsed subpackets, in order.
  31. rawSubpackets []outputSubpacket
  32. // The following are optional so are nil when not included in the
  33. // signature.
  34. SigLifetimeSecs, KeyLifetimeSecs *uint32
  35. PreferredSymmetric, PreferredHash, PreferredCompression []uint8
  36. IssuerKeyId *uint64
  37. IsPrimaryId *bool
  38. // FlagsValid is set if any flags were given. See RFC 4880, section
  39. // 5.2.3.21 for details.
  40. FlagsValid bool
  41. FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
  42. outSubpackets []outputSubpacket
  43. }
  44. func (sig *Signature) parse(r io.Reader) (err error) {
  45. // RFC 4880, section 5.2.3
  46. var buf [5]byte
  47. _, err = readFull(r, buf[:1])
  48. if err != nil {
  49. return
  50. }
  51. if buf[0] != 4 {
  52. err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
  53. return
  54. }
  55. _, err = readFull(r, buf[:5])
  56. if err != nil {
  57. return
  58. }
  59. sig.SigType = SignatureType(buf[0])
  60. sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
  61. switch sig.PubKeyAlgo {
  62. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
  63. default:
  64. err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
  65. return
  66. }
  67. var ok bool
  68. sig.Hash, ok = s2k.HashIdToHash(buf[2])
  69. if !ok {
  70. return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
  71. }
  72. hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
  73. l := 6 + hashedSubpacketsLength
  74. sig.HashSuffix = make([]byte, l+6)
  75. sig.HashSuffix[0] = 4
  76. copy(sig.HashSuffix[1:], buf[:5])
  77. hashedSubpackets := sig.HashSuffix[6:l]
  78. _, err = readFull(r, hashedSubpackets)
  79. if err != nil {
  80. return
  81. }
  82. // See RFC 4880, section 5.2.4
  83. trailer := sig.HashSuffix[l:]
  84. trailer[0] = 4
  85. trailer[1] = 0xff
  86. trailer[2] = uint8(l >> 24)
  87. trailer[3] = uint8(l >> 16)
  88. trailer[4] = uint8(l >> 8)
  89. trailer[5] = uint8(l)
  90. err = parseSignatureSubpackets(sig, hashedSubpackets, true)
  91. if err != nil {
  92. return
  93. }
  94. _, err = readFull(r, buf[:2])
  95. if err != nil {
  96. return
  97. }
  98. unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
  99. unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
  100. _, err = readFull(r, unhashedSubpackets)
  101. if err != nil {
  102. return
  103. }
  104. err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
  105. if err != nil {
  106. return
  107. }
  108. _, err = readFull(r, sig.HashTag[:2])
  109. if err != nil {
  110. return
  111. }
  112. switch sig.PubKeyAlgo {
  113. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  114. sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
  115. case PubKeyAlgoDSA:
  116. sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
  117. if err == nil {
  118. sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
  119. }
  120. default:
  121. panic("unreachable")
  122. }
  123. return
  124. }
  125. // parseSignatureSubpackets parses subpackets of the main signature packet. See
  126. // RFC 4880, section 5.2.3.1.
  127. func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
  128. for len(subpackets) > 0 {
  129. subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
  130. if err != nil {
  131. return
  132. }
  133. }
  134. if sig.CreationTime.IsZero() {
  135. err = errors.StructuralError("no creation time in signature")
  136. }
  137. return
  138. }
  139. type signatureSubpacketType uint8
  140. const (
  141. creationTimeSubpacket signatureSubpacketType = 2
  142. signatureExpirationSubpacket signatureSubpacketType = 3
  143. keyExpirationSubpacket signatureSubpacketType = 9
  144. prefSymmetricAlgosSubpacket signatureSubpacketType = 11
  145. issuerSubpacket signatureSubpacketType = 16
  146. prefHashAlgosSubpacket signatureSubpacketType = 21
  147. prefCompressionSubpacket signatureSubpacketType = 22
  148. primaryUserIdSubpacket signatureSubpacketType = 25
  149. keyFlagsSubpacket signatureSubpacketType = 27
  150. )
  151. // parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
  152. func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
  153. // RFC 4880, section 5.2.3.1
  154. var (
  155. length uint32
  156. packetType signatureSubpacketType
  157. isCritical bool
  158. )
  159. switch {
  160. case subpacket[0] < 192:
  161. length = uint32(subpacket[0])
  162. subpacket = subpacket[1:]
  163. case subpacket[0] < 255:
  164. if len(subpacket) < 2 {
  165. goto Truncated
  166. }
  167. length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
  168. subpacket = subpacket[2:]
  169. default:
  170. if len(subpacket) < 5 {
  171. goto Truncated
  172. }
  173. length = uint32(subpacket[1])<<24 |
  174. uint32(subpacket[2])<<16 |
  175. uint32(subpacket[3])<<8 |
  176. uint32(subpacket[4])
  177. subpacket = subpacket[5:]
  178. }
  179. if length > uint32(len(subpacket)) {
  180. goto Truncated
  181. }
  182. rest = subpacket[length:]
  183. subpacket = subpacket[:length]
  184. if len(subpacket) == 0 {
  185. err = errors.StructuralError("zero length signature subpacket")
  186. return
  187. }
  188. packetType = signatureSubpacketType(subpacket[0] & 0x7f)
  189. isCritical = subpacket[0]&0x80 == 0x80
  190. subpacket = subpacket[1:]
  191. sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
  192. switch packetType {
  193. case creationTimeSubpacket:
  194. if !isHashed {
  195. err = errors.StructuralError("signature creation time in non-hashed area")
  196. return
  197. }
  198. if len(subpacket) != 4 {
  199. err = errors.StructuralError("signature creation time not four bytes")
  200. return
  201. }
  202. t := binary.BigEndian.Uint32(subpacket)
  203. sig.CreationTime = time.Unix(int64(t), 0)
  204. case signatureExpirationSubpacket:
  205. // Signature expiration time, section 5.2.3.10
  206. if !isHashed {
  207. return
  208. }
  209. if len(subpacket) != 4 {
  210. err = errors.StructuralError("expiration subpacket with bad length")
  211. return
  212. }
  213. sig.SigLifetimeSecs = new(uint32)
  214. *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
  215. case keyExpirationSubpacket:
  216. // Key expiration time, section 5.2.3.6
  217. if !isHashed {
  218. return
  219. }
  220. if len(subpacket) != 4 {
  221. err = errors.StructuralError("key expiration subpacket with bad length")
  222. return
  223. }
  224. sig.KeyLifetimeSecs = new(uint32)
  225. *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
  226. case prefSymmetricAlgosSubpacket:
  227. // Preferred symmetric algorithms, section 5.2.3.7
  228. if !isHashed {
  229. return
  230. }
  231. sig.PreferredSymmetric = make([]byte, len(subpacket))
  232. copy(sig.PreferredSymmetric, subpacket)
  233. case issuerSubpacket:
  234. // Issuer, section 5.2.3.5
  235. if len(subpacket) != 8 {
  236. err = errors.StructuralError("issuer subpacket with bad length")
  237. return
  238. }
  239. sig.IssuerKeyId = new(uint64)
  240. *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
  241. case prefHashAlgosSubpacket:
  242. // Preferred hash algorithms, section 5.2.3.8
  243. if !isHashed {
  244. return
  245. }
  246. sig.PreferredHash = make([]byte, len(subpacket))
  247. copy(sig.PreferredHash, subpacket)
  248. case prefCompressionSubpacket:
  249. // Preferred compression algorithms, section 5.2.3.9
  250. if !isHashed {
  251. return
  252. }
  253. sig.PreferredCompression = make([]byte, len(subpacket))
  254. copy(sig.PreferredCompression, subpacket)
  255. case primaryUserIdSubpacket:
  256. // Primary User ID, section 5.2.3.19
  257. if !isHashed {
  258. return
  259. }
  260. if len(subpacket) != 1 {
  261. err = errors.StructuralError("primary user id subpacket with bad length")
  262. return
  263. }
  264. sig.IsPrimaryId = new(bool)
  265. if subpacket[0] > 0 {
  266. *sig.IsPrimaryId = true
  267. }
  268. case keyFlagsSubpacket:
  269. // Key flags, section 5.2.3.21
  270. if !isHashed {
  271. return
  272. }
  273. if len(subpacket) == 0 {
  274. err = errors.StructuralError("empty key flags subpacket")
  275. return
  276. }
  277. sig.FlagsValid = true
  278. if subpacket[0]&1 != 0 {
  279. sig.FlagCertify = true
  280. }
  281. if subpacket[0]&2 != 0 {
  282. sig.FlagSign = true
  283. }
  284. if subpacket[0]&4 != 0 {
  285. sig.FlagEncryptCommunications = true
  286. }
  287. if subpacket[0]&8 != 0 {
  288. sig.FlagEncryptStorage = true
  289. }
  290. default:
  291. if isCritical {
  292. err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
  293. return
  294. }
  295. }
  296. return
  297. Truncated:
  298. err = errors.StructuralError("signature subpacket truncated")
  299. return
  300. }
  301. // subpacketLengthLength returns the length, in bytes, of an encoded length value.
  302. func subpacketLengthLength(length int) int {
  303. if length < 192 {
  304. return 1
  305. }
  306. if length < 16320 {
  307. return 2
  308. }
  309. return 5
  310. }
  311. // serializeSubpacketLength marshals the given length into to.
  312. func serializeSubpacketLength(to []byte, length int) int {
  313. if length < 192 {
  314. to[0] = byte(length)
  315. return 1
  316. }
  317. if length < 16320 {
  318. length -= 192
  319. to[0] = byte(length >> 8)
  320. to[1] = byte(length)
  321. return 2
  322. }
  323. to[0] = 255
  324. to[1] = byte(length >> 24)
  325. to[2] = byte(length >> 16)
  326. to[3] = byte(length >> 8)
  327. to[4] = byte(length)
  328. return 5
  329. }
  330. // subpacketsLength returns the serialized length, in bytes, of the given
  331. // subpackets.
  332. func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
  333. for _, subpacket := range subpackets {
  334. if subpacket.hashed == hashed {
  335. length += subpacketLengthLength(len(subpacket.contents) + 1)
  336. length += 1 // type byte
  337. length += len(subpacket.contents)
  338. }
  339. }
  340. return
  341. }
  342. // serializeSubpackets marshals the given subpackets into to.
  343. func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
  344. for _, subpacket := range subpackets {
  345. if subpacket.hashed == hashed {
  346. n := serializeSubpacketLength(to, len(subpacket.contents)+1)
  347. to[n] = byte(subpacket.subpacketType)
  348. to = to[1+n:]
  349. n = copy(to, subpacket.contents)
  350. to = to[n:]
  351. }
  352. }
  353. return
  354. }
  355. // buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
  356. func (sig *Signature) buildHashSuffix() (err error) {
  357. hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
  358. var ok bool
  359. l := 6 + hashedSubpacketsLen
  360. sig.HashSuffix = make([]byte, l+6)
  361. sig.HashSuffix[0] = 4
  362. sig.HashSuffix[1] = uint8(sig.SigType)
  363. sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
  364. sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
  365. if !ok {
  366. sig.HashSuffix = nil
  367. return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
  368. }
  369. sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
  370. sig.HashSuffix[5] = byte(hashedSubpacketsLen)
  371. serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
  372. trailer := sig.HashSuffix[l:]
  373. trailer[0] = 4
  374. trailer[1] = 0xff
  375. trailer[2] = byte(l >> 24)
  376. trailer[3] = byte(l >> 16)
  377. trailer[4] = byte(l >> 8)
  378. trailer[5] = byte(l)
  379. return
  380. }
  381. func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
  382. err = sig.buildHashSuffix()
  383. if err != nil {
  384. return
  385. }
  386. h.Write(sig.HashSuffix)
  387. digest = h.Sum(nil)
  388. copy(sig.HashTag[:], digest)
  389. return
  390. }
  391. // Sign signs a message with a private key. The hash, h, must contain
  392. // the hash of the message to be signed and will be mutated by this function.
  393. // On success, the signature is stored in sig. Call Serialize to write it out.
  394. func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) {
  395. sig.outSubpackets = sig.buildSubpackets()
  396. digest, err := sig.signPrepareHash(h)
  397. if err != nil {
  398. return
  399. }
  400. switch priv.PubKeyAlgo {
  401. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  402. sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
  403. sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
  404. case PubKeyAlgoDSA:
  405. dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
  406. // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
  407. subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
  408. if len(digest) > subgroupSize {
  409. digest = digest[:subgroupSize]
  410. }
  411. r, s, err := dsa.Sign(rand, dsaPriv, digest)
  412. if err == nil {
  413. sig.DSASigR.bytes = r.Bytes()
  414. sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
  415. sig.DSASigS.bytes = s.Bytes()
  416. sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
  417. }
  418. default:
  419. err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
  420. }
  421. return
  422. }
  423. // SignUserId computes a signature from priv, asserting that pub is a valid
  424. // key for the identity id. On success, the signature is stored in sig. Call
  425. // Serialize to write it out.
  426. func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error {
  427. h, err := userIdSignatureHash(id, pub, sig)
  428. if err != nil {
  429. return nil
  430. }
  431. return sig.Sign(rand, h, priv)
  432. }
  433. // SignKey computes a signature from priv, asserting that pub is a subkey. On
  434. // success, the signature is stored in sig. Call Serialize to write it out.
  435. func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error {
  436. h, err := keySignatureHash(&priv.PublicKey, pub, sig)
  437. if err != nil {
  438. return err
  439. }
  440. return sig.Sign(rand, h, priv)
  441. }
  442. // Serialize marshals sig to w. SignRSA or SignDSA must have been called first.
  443. func (sig *Signature) Serialize(w io.Writer) (err error) {
  444. if len(sig.outSubpackets) == 0 {
  445. sig.outSubpackets = sig.rawSubpackets
  446. }
  447. if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
  448. return errors.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize")
  449. }
  450. sigLength := 0
  451. switch sig.PubKeyAlgo {
  452. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  453. sigLength = 2 + len(sig.RSASignature.bytes)
  454. case PubKeyAlgoDSA:
  455. sigLength = 2 + len(sig.DSASigR.bytes)
  456. sigLength += 2 + len(sig.DSASigS.bytes)
  457. default:
  458. panic("impossible")
  459. }
  460. unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
  461. length := len(sig.HashSuffix) - 6 /* trailer not included */ +
  462. 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
  463. 2 /* hash tag */ + sigLength
  464. err = serializeHeader(w, packetTypeSignature, length)
  465. if err != nil {
  466. return
  467. }
  468. _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
  469. if err != nil {
  470. return
  471. }
  472. unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
  473. unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
  474. unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
  475. serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
  476. _, err = w.Write(unhashedSubpackets)
  477. if err != nil {
  478. return
  479. }
  480. _, err = w.Write(sig.HashTag[:])
  481. if err != nil {
  482. return
  483. }
  484. switch sig.PubKeyAlgo {
  485. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  486. err = writeMPIs(w, sig.RSASignature)
  487. case PubKeyAlgoDSA:
  488. err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
  489. default:
  490. panic("impossible")
  491. }
  492. return
  493. }
  494. // outputSubpacket represents a subpacket to be marshaled.
  495. type outputSubpacket struct {
  496. hashed bool // true if this subpacket is in the hashed area.
  497. subpacketType signatureSubpacketType
  498. isCritical bool
  499. contents []byte
  500. }
  501. func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
  502. creationTime := make([]byte, 4)
  503. binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
  504. subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
  505. if sig.IssuerKeyId != nil {
  506. keyId := make([]byte, 8)
  507. binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
  508. subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
  509. }
  510. if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
  511. sigLifetime := make([]byte, 4)
  512. binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
  513. subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
  514. }
  515. // Key flags may only appear in self-signatures or certification signatures.
  516. if sig.FlagsValid {
  517. var flags byte
  518. if sig.FlagCertify {
  519. flags |= 1
  520. }
  521. if sig.FlagSign {
  522. flags |= 2
  523. }
  524. if sig.FlagEncryptCommunications {
  525. flags |= 4
  526. }
  527. if sig.FlagEncryptStorage {
  528. flags |= 8
  529. }
  530. subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
  531. }
  532. // The following subpackets may only appear in self-signatures
  533. if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
  534. keyLifetime := make([]byte, 4)
  535. binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
  536. subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
  537. }
  538. if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
  539. subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
  540. }
  541. if len(sig.PreferredSymmetric) > 0 {
  542. subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
  543. }
  544. if len(sig.PreferredHash) > 0 {
  545. subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
  546. }
  547. if len(sig.PreferredCompression) > 0 {
  548. subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
  549. }
  550. return
  551. }