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.
10 "crypto/openpgp/elgamal"
11 error_ "crypto/openpgp/error"
21 // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
22 type PublicKey struct {
23 CreationTime uint32 // seconds since the epoch
24 PubKeyAlgo PublicKeyAlgorithm
25 PublicKey interface{} // Either a *rsa.PublicKey or *dsa.PublicKey
30 n, e, p, q, g, y parsedMPI
33 func fromBig(n *big.Int) parsedMPI {
36 bitLength: uint16(n.BitLen()),
40 // NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
41 func NewRSAPublicKey(creationTimeSecs uint32, pub *rsa.PublicKey, isSubkey bool) *PublicKey {
43 CreationTime: creationTimeSecs,
44 PubKeyAlgo: PubKeyAlgoRSA,
48 e: fromBig(big.NewInt(int64(pub.E))),
51 pk.setFingerPrintAndKeyId()
55 func (pk *PublicKey) parse(r io.Reader) (err error) {
56 // RFC 4880, section 5.5.2
58 _, err = readFull(r, buf[:])
63 return error_.UnsupportedError("public key version")
65 pk.CreationTime = uint32(buf[1])<<24 | uint32(buf[2])<<16 | uint32(buf[3])<<8 | uint32(buf[4])
66 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
67 switch pk.PubKeyAlgo {
68 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
72 case PubKeyAlgoElGamal:
73 err = pk.parseElGamal(r)
75 err = error_.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
81 pk.setFingerPrintAndKeyId()
85 func (pk *PublicKey) setFingerPrintAndKeyId() {
86 // RFC 4880, section 12.2
87 fingerPrint := sha1.New()
88 pk.SerializeSignaturePrefix(fingerPrint)
89 pk.serializeWithoutHeaders(fingerPrint)
90 copy(pk.Fingerprint[:], fingerPrint.Sum())
91 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
94 // parseRSA parses RSA public key material from the given Reader. See RFC 4880,
96 func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
97 pk.n.bytes, pk.n.bitLength, err = readMPI(r)
101 pk.e.bytes, pk.e.bitLength, err = readMPI(r)
106 if len(pk.e.bytes) > 3 {
107 err = error_.UnsupportedError("large public exponent")
110 rsa := &rsa.PublicKey{
111 N: new(big.Int).SetBytes(pk.n.bytes),
114 for i := 0; i < len(pk.e.bytes); i++ {
116 rsa.E |= int(pk.e.bytes[i])
122 // parseDSA parses DSA public key material from the given Reader. See RFC 4880,
124 func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
125 pk.p.bytes, pk.p.bitLength, err = readMPI(r)
129 pk.q.bytes, pk.q.bitLength, err = readMPI(r)
133 pk.g.bytes, pk.g.bitLength, err = readMPI(r)
137 pk.y.bytes, pk.y.bitLength, err = readMPI(r)
142 dsa := new(dsa.PublicKey)
143 dsa.P = new(big.Int).SetBytes(pk.p.bytes)
144 dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
145 dsa.G = new(big.Int).SetBytes(pk.g.bytes)
146 dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
151 // parseElGamal parses ElGamal public key material from the given Reader. See
152 // RFC 4880, section 5.5.2.
153 func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
154 pk.p.bytes, pk.p.bitLength, err = readMPI(r)
158 pk.g.bytes, pk.g.bitLength, err = readMPI(r)
162 pk.y.bytes, pk.y.bitLength, err = readMPI(r)
167 elgamal := new(elgamal.PublicKey)
168 elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
169 elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
170 elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
171 pk.PublicKey = elgamal
175 // SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
176 // The prefix is used when calculating a signature over this public key. See
177 // RFC 4880, section 5.2.4.
178 func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
180 switch pk.PubKeyAlgo {
181 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
182 pLength += 2 + uint16(len(pk.n.bytes))
183 pLength += 2 + uint16(len(pk.e.bytes))
185 pLength += 2 + uint16(len(pk.p.bytes))
186 pLength += 2 + uint16(len(pk.q.bytes))
187 pLength += 2 + uint16(len(pk.g.bytes))
188 pLength += 2 + uint16(len(pk.y.bytes))
189 case PubKeyAlgoElGamal:
190 pLength += 2 + uint16(len(pk.p.bytes))
191 pLength += 2 + uint16(len(pk.g.bytes))
192 pLength += 2 + uint16(len(pk.y.bytes))
194 panic("unknown public key algorithm")
197 h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
201 func (pk *PublicKey) Serialize(w io.Writer) (err error) {
202 length := 6 // 6 byte header
204 switch pk.PubKeyAlgo {
205 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
206 length += 2 + len(pk.n.bytes)
207 length += 2 + len(pk.e.bytes)
209 length += 2 + len(pk.p.bytes)
210 length += 2 + len(pk.q.bytes)
211 length += 2 + len(pk.g.bytes)
212 length += 2 + len(pk.y.bytes)
213 case PubKeyAlgoElGamal:
214 length += 2 + len(pk.p.bytes)
215 length += 2 + len(pk.g.bytes)
216 length += 2 + len(pk.y.bytes)
218 panic("unknown public key algorithm")
221 packetType := packetTypePublicKey
223 packetType = packetTypePublicSubkey
225 err = serializeHeader(w, packetType, length)
229 return pk.serializeWithoutHeaders(w)
232 // serializeWithoutHeaders marshals the PublicKey to w in the form of an
233 // OpenPGP public key packet, not including the packet header.
234 func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
237 buf[1] = byte(pk.CreationTime >> 24)
238 buf[2] = byte(pk.CreationTime >> 16)
239 buf[3] = byte(pk.CreationTime >> 8)
240 buf[4] = byte(pk.CreationTime)
241 buf[5] = byte(pk.PubKeyAlgo)
243 _, err = w.Write(buf[:])
248 switch pk.PubKeyAlgo {
249 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
250 return writeMPIs(w, pk.n, pk.e)
252 return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
253 case PubKeyAlgoElGamal:
254 return writeMPIs(w, pk.p, pk.g, pk.y)
256 return error_.InvalidArgumentError("bad public-key algorithm")
259 // CanSign returns true iff this public key can generate signatures
260 func (pk *PublicKey) CanSign() bool {
261 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
264 // VerifySignature returns nil iff sig is a valid signature, made by this
265 // public key, of the data hashed into signed. signed is mutated by this call.
266 func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
268 return error_.InvalidArgumentError("public key cannot generate signatures")
271 signed.Write(sig.HashSuffix)
272 hashBytes := signed.Sum()
274 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
275 return error_.SignatureError("hash tag doesn't match")
278 if pk.PubKeyAlgo != sig.PubKeyAlgo {
279 return error_.InvalidArgumentError("public key and signature use different algorithms")
282 switch pk.PubKeyAlgo {
283 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
284 rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
285 err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
287 return error_.SignatureError("RSA verification failure")
291 dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
292 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
293 return error_.SignatureError("DSA verification failure")
297 panic("shouldn't happen")
302 // keySignatureHash returns a Hash of the message that needs to be signed for
303 // pk to assert a subkey relationship to signed.
304 func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err error) {
307 return nil, error_.UnsupportedError("hash function")
310 // RFC 4880, section 5.2.4
311 pk.SerializeSignaturePrefix(h)
312 pk.serializeWithoutHeaders(h)
313 signed.SerializeSignaturePrefix(h)
314 signed.serializeWithoutHeaders(h)
318 // VerifyKeySignature returns nil iff sig is a valid signature, made by this
319 // public key, of signed.
320 func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) {
321 h, err := keySignatureHash(pk, signed, sig)
325 return pk.VerifySignature(h, sig)
328 // userIdSignatureHash returns a Hash of the message that needs to be signed
329 // to assert that pk is a valid key for id.
330 func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err error) {
333 return nil, error_.UnsupportedError("hash function")
336 // RFC 4880, section 5.2.4
337 pk.SerializeSignaturePrefix(h)
338 pk.serializeWithoutHeaders(h)
342 buf[1] = byte(len(id) >> 24)
343 buf[2] = byte(len(id) >> 16)
344 buf[3] = byte(len(id) >> 8)
345 buf[4] = byte(len(id))
352 // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
353 // public key, of id.
354 func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err error) {
355 h, err := userIdSignatureHash(id, pk, sig)
359 return pk.VerifySignature(h, sig)
362 // KeyIdString returns the public key's fingerprint in capital hex
363 // (e.g. "6C7EE1B8621CC013").
364 func (pk *PublicKey) KeyIdString() string {
365 return fmt.Sprintf("%X", pk.Fingerprint[12:20])
368 // KeyIdShortString returns the short form of public key's fingerprint
369 // in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
370 func (pk *PublicKey) KeyIdShortString() string {
371 return fmt.Sprintf("%X", pk.Fingerprint[16:20])
374 // A parsedMPI is used to store the contents of a big integer, along with the
375 // bit length that was specified in the original input. This allows the MPI to
376 // be reserialized exactly.
377 type parsedMPI struct {
382 // writeMPIs is a utility function for serializing several big integers to the
384 func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
385 for _, mpi := range mpis {
386 err = writeMPI(w, mpi.bitLength, mpi.bytes)