public_key.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  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. "bytes"
  7. "code.google.com/p/go.crypto/openpgp/elgamal"
  8. "code.google.com/p/go.crypto/openpgp/errors"
  9. "crypto/dsa"
  10. "crypto/ecdsa"
  11. "crypto/elliptic"
  12. "crypto/rsa"
  13. "crypto/sha1"
  14. _ "crypto/sha256"
  15. _ "crypto/sha512"
  16. "encoding/binary"
  17. "fmt"
  18. "hash"
  19. "io"
  20. "math/big"
  21. "strconv"
  22. "time"
  23. )
  24. var (
  25. // NIST curve P-256
  26. oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
  27. // NIST curve P-384
  28. oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
  29. // NIST curve P-521
  30. oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
  31. )
  32. const maxOIDLength = 8
  33. // ecdsaKey stores the algorithm-specific fields for ECDSA keys.
  34. // as defined in RFC 6637, Section 9.
  35. type ecdsaKey struct {
  36. // oid contains the OID byte sequence identifying the elliptic curve used
  37. oid []byte
  38. // p contains the elliptic curve point that represents the public key
  39. p parsedMPI
  40. }
  41. // parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
  42. func parseOID(r io.Reader) (oid []byte, err error) {
  43. buf := make([]byte, maxOIDLength)
  44. if _, err = readFull(r, buf[:1]); err != nil {
  45. return
  46. }
  47. oidLen := buf[0]
  48. if int(oidLen) > len(buf) {
  49. err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen)))
  50. return
  51. }
  52. oid = buf[:oidLen]
  53. _, err = readFull(r, oid)
  54. return
  55. }
  56. func (f *ecdsaKey) parse(r io.Reader) (err error) {
  57. if f.oid, err = parseOID(r); err != nil {
  58. return err
  59. }
  60. f.p.bytes, f.p.bitLength, err = readMPI(r)
  61. return
  62. }
  63. func (f *ecdsaKey) serialize(w io.Writer) (err error) {
  64. buf := make([]byte, maxOIDLength+1)
  65. buf[0] = byte(len(f.oid))
  66. copy(buf[1:], f.oid)
  67. if _, err = w.Write(buf[:len(f.oid)+1]); err != nil {
  68. return
  69. }
  70. return writeMPIs(w, f.p)
  71. }
  72. func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
  73. var c elliptic.Curve
  74. if bytes.Equal(f.oid, oidCurveP256) {
  75. c = elliptic.P256()
  76. } else if bytes.Equal(f.oid, oidCurveP384) {
  77. c = elliptic.P384()
  78. } else if bytes.Equal(f.oid, oidCurveP521) {
  79. c = elliptic.P521()
  80. } else {
  81. return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
  82. }
  83. x, y := elliptic.Unmarshal(c, f.p.bytes)
  84. if x == nil {
  85. return nil, errors.UnsupportedError("failed to parse EC point")
  86. }
  87. return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
  88. }
  89. func (f *ecdsaKey) byteLen() int {
  90. return 1 + len(f.oid) + 2 + len(f.p.bytes)
  91. }
  92. type kdfHashFunction byte
  93. type kdfAlgorithm byte
  94. // ecdhKdf stores key derivation function parameters
  95. // used for ECDH encryption. See RFC 6637, Section 9.
  96. type ecdhKdf struct {
  97. KdfHash kdfHashFunction
  98. KdfAlgo kdfAlgorithm
  99. }
  100. func (f *ecdhKdf) parse(r io.Reader) (err error) {
  101. buf := make([]byte, 1)
  102. if _, err = readFull(r, buf); err != nil {
  103. return
  104. }
  105. kdfLen := int(buf[0])
  106. if kdfLen < 3 {
  107. return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
  108. }
  109. buf = make([]byte, kdfLen)
  110. if _, err = readFull(r, buf); err != nil {
  111. return
  112. }
  113. reserved := int(buf[0])
  114. f.KdfHash = kdfHashFunction(buf[1])
  115. f.KdfAlgo = kdfAlgorithm(buf[2])
  116. if reserved != 0x01 {
  117. return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved))
  118. }
  119. return
  120. }
  121. func (f *ecdhKdf) serialize(w io.Writer) (err error) {
  122. buf := make([]byte, 4)
  123. // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
  124. buf[0] = byte(0x03) // Length of the following fields
  125. buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
  126. buf[2] = byte(f.KdfHash)
  127. buf[3] = byte(f.KdfAlgo)
  128. _, err = w.Write(buf[:])
  129. return
  130. }
  131. func (f *ecdhKdf) byteLen() int {
  132. return 4
  133. }
  134. // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
  135. type PublicKey struct {
  136. CreationTime time.Time
  137. PubKeyAlgo PublicKeyAlgorithm
  138. PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
  139. Fingerprint [20]byte
  140. KeyId uint64
  141. IsSubkey bool
  142. n, e, p, q, g, y parsedMPI
  143. // RFC 6637 fields
  144. ec *ecdsaKey
  145. ecdh *ecdhKdf
  146. }
  147. func fromBig(n *big.Int) parsedMPI {
  148. return parsedMPI{
  149. bytes: n.Bytes(),
  150. bitLength: uint16(n.BitLen()),
  151. }
  152. }
  153. // NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
  154. func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
  155. pk := &PublicKey{
  156. CreationTime: creationTime,
  157. PubKeyAlgo: PubKeyAlgoRSA,
  158. PublicKey: pub,
  159. n: fromBig(pub.N),
  160. e: fromBig(big.NewInt(int64(pub.E))),
  161. }
  162. pk.setFingerPrintAndKeyId()
  163. return pk
  164. }
  165. // NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
  166. func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
  167. pk := &PublicKey{
  168. CreationTime: creationTime,
  169. PubKeyAlgo: PubKeyAlgoDSA,
  170. PublicKey: pub,
  171. p: fromBig(pub.P),
  172. q: fromBig(pub.Q),
  173. g: fromBig(pub.G),
  174. y: fromBig(pub.Y),
  175. }
  176. pk.setFingerPrintAndKeyId()
  177. return pk
  178. }
  179. func (pk *PublicKey) parse(r io.Reader) (err error) {
  180. // RFC 4880, section 5.5.2
  181. var buf [6]byte
  182. _, err = readFull(r, buf[:])
  183. if err != nil {
  184. return
  185. }
  186. if buf[0] != 4 {
  187. return errors.UnsupportedError("public key version")
  188. }
  189. pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
  190. pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
  191. switch pk.PubKeyAlgo {
  192. case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
  193. err = pk.parseRSA(r)
  194. case PubKeyAlgoDSA:
  195. err = pk.parseDSA(r)
  196. case PubKeyAlgoElGamal:
  197. err = pk.parseElGamal(r)
  198. case PubKeyAlgoECDSA:
  199. pk.ec = new(ecdsaKey)
  200. if err = pk.ec.parse(r); err != nil {
  201. return err
  202. }
  203. pk.PublicKey, err = pk.ec.newECDSA()
  204. case PubKeyAlgoECDH:
  205. pk.ec = new(ecdsaKey)
  206. if err = pk.ec.parse(r); err != nil {
  207. return
  208. }
  209. pk.ecdh = new(ecdhKdf)
  210. if err = pk.ecdh.parse(r); err != nil {
  211. return
  212. }
  213. // The ECDH key is stored in an ecdsa.PublicKey for convenience.
  214. pk.PublicKey, err = pk.ec.newECDSA()
  215. default:
  216. err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
  217. }
  218. if err != nil {
  219. return
  220. }
  221. pk.setFingerPrintAndKeyId()
  222. return
  223. }
  224. func (pk *PublicKey) setFingerPrintAndKeyId() {
  225. // RFC 4880, section 12.2
  226. fingerPrint := sha1.New()
  227. pk.SerializeSignaturePrefix(fingerPrint)
  228. pk.serializeWithoutHeaders(fingerPrint)
  229. copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
  230. pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
  231. }
  232. // parseRSA parses RSA public key material from the given Reader. See RFC 4880,
  233. // section 5.5.2.
  234. func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
  235. pk.n.bytes, pk.n.bitLength, err = readMPI(r)
  236. if err != nil {
  237. return
  238. }
  239. pk.e.bytes, pk.e.bitLength, err = readMPI(r)
  240. if err != nil {
  241. return
  242. }
  243. if len(pk.e.bytes) > 3 {
  244. err = errors.UnsupportedError("large public exponent")
  245. return
  246. }
  247. rsa := &rsa.PublicKey{
  248. N: new(big.Int).SetBytes(pk.n.bytes),
  249. E: 0,
  250. }
  251. for i := 0; i < len(pk.e.bytes); i++ {
  252. rsa.E <<= 8
  253. rsa.E |= int(pk.e.bytes[i])
  254. }
  255. pk.PublicKey = rsa
  256. return
  257. }
  258. // parseDSA parses DSA public key material from the given Reader. See RFC 4880,
  259. // section 5.5.2.
  260. func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
  261. pk.p.bytes, pk.p.bitLength, err = readMPI(r)
  262. if err != nil {
  263. return
  264. }
  265. pk.q.bytes, pk.q.bitLength, err = readMPI(r)
  266. if err != nil {
  267. return
  268. }
  269. pk.g.bytes, pk.g.bitLength, err = readMPI(r)
  270. if err != nil {
  271. return
  272. }
  273. pk.y.bytes, pk.y.bitLength, err = readMPI(r)
  274. if err != nil {
  275. return
  276. }
  277. dsa := new(dsa.PublicKey)
  278. dsa.P = new(big.Int).SetBytes(pk.p.bytes)
  279. dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
  280. dsa.G = new(big.Int).SetBytes(pk.g.bytes)
  281. dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
  282. pk.PublicKey = dsa
  283. return
  284. }
  285. // parseElGamal parses ElGamal public key material from the given Reader. See
  286. // RFC 4880, section 5.5.2.
  287. func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
  288. pk.p.bytes, pk.p.bitLength, err = readMPI(r)
  289. if err != nil {
  290. return
  291. }
  292. pk.g.bytes, pk.g.bitLength, err = readMPI(r)
  293. if err != nil {
  294. return
  295. }
  296. pk.y.bytes, pk.y.bitLength, err = readMPI(r)
  297. if err != nil {
  298. return
  299. }
  300. elgamal := new(elgamal.PublicKey)
  301. elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
  302. elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
  303. elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
  304. pk.PublicKey = elgamal
  305. return
  306. }
  307. // SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
  308. // The prefix is used when calculating a signature over this public key. See
  309. // RFC 4880, section 5.2.4.
  310. func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
  311. var pLength uint16
  312. switch pk.PubKeyAlgo {
  313. case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
  314. pLength += 2 + uint16(len(pk.n.bytes))
  315. pLength += 2 + uint16(len(pk.e.bytes))
  316. case PubKeyAlgoDSA:
  317. pLength += 2 + uint16(len(pk.p.bytes))
  318. pLength += 2 + uint16(len(pk.q.bytes))
  319. pLength += 2 + uint16(len(pk.g.bytes))
  320. pLength += 2 + uint16(len(pk.y.bytes))
  321. case PubKeyAlgoElGamal:
  322. pLength += 2 + uint16(len(pk.p.bytes))
  323. pLength += 2 + uint16(len(pk.g.bytes))
  324. pLength += 2 + uint16(len(pk.y.bytes))
  325. case PubKeyAlgoECDSA:
  326. pLength += uint16(pk.ec.byteLen())
  327. case PubKeyAlgoECDH:
  328. pLength += uint16(pk.ec.byteLen())
  329. pLength += uint16(pk.ecdh.byteLen())
  330. default:
  331. panic("unknown public key algorithm")
  332. }
  333. pLength += 6
  334. h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
  335. return
  336. }
  337. func (pk *PublicKey) Serialize(w io.Writer) (err error) {
  338. length := 6 // 6 byte header
  339. switch pk.PubKeyAlgo {
  340. case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
  341. length += 2 + len(pk.n.bytes)
  342. length += 2 + len(pk.e.bytes)
  343. case PubKeyAlgoDSA:
  344. length += 2 + len(pk.p.bytes)
  345. length += 2 + len(pk.q.bytes)
  346. length += 2 + len(pk.g.bytes)
  347. length += 2 + len(pk.y.bytes)
  348. case PubKeyAlgoElGamal:
  349. length += 2 + len(pk.p.bytes)
  350. length += 2 + len(pk.g.bytes)
  351. length += 2 + len(pk.y.bytes)
  352. case PubKeyAlgoECDSA:
  353. length += pk.ec.byteLen()
  354. case PubKeyAlgoECDH:
  355. length += pk.ec.byteLen()
  356. length += pk.ecdh.byteLen()
  357. default:
  358. panic("unknown public key algorithm")
  359. }
  360. packetType := packetTypePublicKey
  361. if pk.IsSubkey {
  362. packetType = packetTypePublicSubkey
  363. }
  364. err = serializeHeader(w, packetType, length)
  365. if err != nil {
  366. return
  367. }
  368. return pk.serializeWithoutHeaders(w)
  369. }
  370. // serializeWithoutHeaders marshals the PublicKey to w in the form of an
  371. // OpenPGP public key packet, not including the packet header.
  372. func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
  373. var buf [6]byte
  374. buf[0] = 4
  375. t := uint32(pk.CreationTime.Unix())
  376. buf[1] = byte(t >> 24)
  377. buf[2] = byte(t >> 16)
  378. buf[3] = byte(t >> 8)
  379. buf[4] = byte(t)
  380. buf[5] = byte(pk.PubKeyAlgo)
  381. _, err = w.Write(buf[:])
  382. if err != nil {
  383. return
  384. }
  385. switch pk.PubKeyAlgo {
  386. case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
  387. return writeMPIs(w, pk.n, pk.e)
  388. case PubKeyAlgoDSA:
  389. return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
  390. case PubKeyAlgoElGamal:
  391. return writeMPIs(w, pk.p, pk.g, pk.y)
  392. case PubKeyAlgoECDSA:
  393. return pk.ec.serialize(w)
  394. case PubKeyAlgoECDH:
  395. if err = pk.ec.serialize(w); err != nil {
  396. return
  397. }
  398. return pk.ecdh.serialize(w)
  399. }
  400. return errors.InvalidArgumentError("bad public-key algorithm")
  401. }
  402. // CanSign returns true iff this public key can generate signatures
  403. func (pk *PublicKey) CanSign() bool {
  404. return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
  405. }
  406. // VerifySignature returns nil iff sig is a valid signature, made by this
  407. // public key, of the data hashed into signed. signed is mutated by this call.
  408. func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
  409. if !pk.CanSign() {
  410. return errors.InvalidArgumentError("public key cannot generate signatures")
  411. }
  412. signed.Write(sig.HashSuffix)
  413. hashBytes := signed.Sum(nil)
  414. if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
  415. return errors.SignatureError("hash tag doesn't match")
  416. }
  417. if pk.PubKeyAlgo != sig.PubKeyAlgo {
  418. return errors.InvalidArgumentError("public key and signature use different algorithms")
  419. }
  420. switch pk.PubKeyAlgo {
  421. case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
  422. rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
  423. err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
  424. if err != nil {
  425. return errors.SignatureError("RSA verification failure")
  426. }
  427. return nil
  428. case PubKeyAlgoDSA:
  429. dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
  430. // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
  431. subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
  432. if len(hashBytes) > subgroupSize {
  433. hashBytes = hashBytes[:subgroupSize]
  434. }
  435. if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
  436. return errors.SignatureError("DSA verification failure")
  437. }
  438. return nil
  439. case PubKeyAlgoECDSA:
  440. ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
  441. if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
  442. return errors.SignatureError("ECDSA verification failure")
  443. }
  444. return nil
  445. default:
  446. return errors.SignatureError("Unsupported public key algorithm used in signature")
  447. }
  448. panic("unreachable")
  449. }
  450. // keySignatureHash returns a Hash of the message that needs to be signed for
  451. // pk to assert a subkey relationship to signed.
  452. func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err error) {
  453. h = sig.Hash.New()
  454. if h == nil {
  455. return nil, errors.UnsupportedError("hash function")
  456. }
  457. // RFC 4880, section 5.2.4
  458. pk.SerializeSignaturePrefix(h)
  459. pk.serializeWithoutHeaders(h)
  460. signed.SerializeSignaturePrefix(h)
  461. signed.serializeWithoutHeaders(h)
  462. return
  463. }
  464. // VerifyKeySignature returns nil iff sig is a valid signature, made by this
  465. // public key, of signed.
  466. func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) {
  467. h, err := keySignatureHash(pk, signed, sig)
  468. if err != nil {
  469. return err
  470. }
  471. return pk.VerifySignature(h, sig)
  472. }
  473. // userIdSignatureHash returns a Hash of the message that needs to be signed
  474. // to assert that pk is a valid key for id.
  475. func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err error) {
  476. h = sig.Hash.New()
  477. if h == nil {
  478. return nil, errors.UnsupportedError("hash function")
  479. }
  480. // RFC 4880, section 5.2.4
  481. pk.SerializeSignaturePrefix(h)
  482. pk.serializeWithoutHeaders(h)
  483. var buf [5]byte
  484. buf[0] = 0xb4
  485. buf[1] = byte(len(id) >> 24)
  486. buf[2] = byte(len(id) >> 16)
  487. buf[3] = byte(len(id) >> 8)
  488. buf[4] = byte(len(id))
  489. h.Write(buf[:])
  490. h.Write([]byte(id))
  491. return
  492. }
  493. // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
  494. // public key, of id.
  495. func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err error) {
  496. h, err := userIdSignatureHash(id, pk, sig)
  497. if err != nil {
  498. return err
  499. }
  500. return pk.VerifySignature(h, sig)
  501. }
  502. // KeyIdString returns the public key's fingerprint in capital hex
  503. // (e.g. "6C7EE1B8621CC013").
  504. func (pk *PublicKey) KeyIdString() string {
  505. return fmt.Sprintf("%X", pk.Fingerprint[12:20])
  506. }
  507. // KeyIdShortString returns the short form of public key's fingerprint
  508. // in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
  509. func (pk *PublicKey) KeyIdShortString() string {
  510. return fmt.Sprintf("%X", pk.Fingerprint[16:20])
  511. }
  512. // A parsedMPI is used to store the contents of a big integer, along with the
  513. // bit length that was specified in the original input. This allows the MPI to
  514. // be reserialized exactly.
  515. type parsedMPI struct {
  516. bytes []byte
  517. bitLength uint16
  518. }
  519. // writeMPIs is a utility function for serializing several big integers to the
  520. // given Writer.
  521. func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
  522. for _, mpi := range mpis {
  523. err = writeMPI(w, mpi.bitLength, mpi.bytes)
  524. if err != nil {
  525. return
  526. }
  527. }
  528. return
  529. }
  530. // BitLength returns the bit length for the given public key.
  531. func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
  532. switch pk.PubKeyAlgo {
  533. case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
  534. bitLength = pk.n.bitLength
  535. case PubKeyAlgoDSA:
  536. bitLength = pk.p.bitLength
  537. case PubKeyAlgoElGamal:
  538. bitLength = pk.p.bitLength
  539. default:
  540. err = errors.InvalidArgumentError("bad public-key algorithm")
  541. }
  542. return
  543. }