~ubuntu-branches/ubuntu/saucy/juju-core/saucy-proposed

« back to all changes in this revision

Viewing changes to src/code.google.com/p/go.crypto/openpgp/packet/public_key.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-07-11 17:18:27 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130711171827-vjqkg40r0dlf7ys2
Tags: 1.11.2-0ubuntu1
* New upstream release.
* Make juju-core the default juju (LP: #1190634):
  - d/control: Add virtual package juju -> juju-core.
  - d/juju-core.postinst.in: Bump priority of alternatives over that of
    python juju packages.
* Enable for all architectures (LP: #1172505):
  - d/control: Version BD on golang-go to >= 2:1.1.1 to ensure CGO
    support for non-x86 archs, make juju-core Arch: any.
  - d/README.source: Dropped - no longer required.
* d/watch: Updated for new upstream tarball naming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        "code.google.com/p/go.crypto/openpgp/elgamal"
 
9
        "code.google.com/p/go.crypto/openpgp/errors"
 
10
        "crypto/dsa"
 
11
        "crypto/rsa"
 
12
        "crypto/sha1"
 
13
        "encoding/binary"
 
14
        "fmt"
 
15
        "hash"
 
16
        "io"
 
17
        "math/big"
 
18
        "strconv"
 
19
        "time"
 
20
)
 
21
 
 
22
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
 
23
type PublicKey struct {
 
24
        CreationTime time.Time
 
25
        PubKeyAlgo   PublicKeyAlgorithm
 
26
        PublicKey    interface{} // Either a *rsa.PublicKey or *dsa.PublicKey
 
27
        Fingerprint  [20]byte
 
28
        KeyId        uint64
 
29
        IsSubkey     bool
 
30
 
 
31
        n, e, p, q, g, y parsedMPI
 
32
}
 
33
 
 
34
func fromBig(n *big.Int) parsedMPI {
 
35
        return parsedMPI{
 
36
                bytes:     n.Bytes(),
 
37
                bitLength: uint16(n.BitLen()),
 
38
        }
 
39
}
 
40
 
 
41
// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
 
42
func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
 
43
        pk := &PublicKey{
 
44
                CreationTime: creationTime,
 
45
                PubKeyAlgo:   PubKeyAlgoRSA,
 
46
                PublicKey:    pub,
 
47
                n:            fromBig(pub.N),
 
48
                e:            fromBig(big.NewInt(int64(pub.E))),
 
49
        }
 
50
 
 
51
        pk.setFingerPrintAndKeyId()
 
52
        return pk
 
53
}
 
54
 
 
55
// NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
 
56
func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
 
57
        pk := &PublicKey{
 
58
                CreationTime: creationTime,
 
59
                PubKeyAlgo:   PubKeyAlgoDSA,
 
60
                PublicKey:    pub,
 
61
                p:            fromBig(pub.P),
 
62
                q:            fromBig(pub.Q),
 
63
                g:            fromBig(pub.G),
 
64
                y:            fromBig(pub.Y),
 
65
        }
 
66
 
 
67
        pk.setFingerPrintAndKeyId()
 
68
        return pk
 
69
}
 
70
 
 
71
func (pk *PublicKey) parse(r io.Reader) (err error) {
 
72
        // RFC 4880, section 5.5.2
 
73
        var buf [6]byte
 
74
        _, err = readFull(r, buf[:])
 
75
        if err != nil {
 
76
                return
 
77
        }
 
78
        if buf[0] != 4 {
 
79
                return errors.UnsupportedError("public key version")
 
80
        }
 
81
        pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
 
82
        pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
 
83
        switch pk.PubKeyAlgo {
 
84
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 
85
                err = pk.parseRSA(r)
 
86
        case PubKeyAlgoDSA:
 
87
                err = pk.parseDSA(r)
 
88
        case PubKeyAlgoElGamal:
 
89
                err = pk.parseElGamal(r)
 
90
        default:
 
91
                err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
 
92
        }
 
93
        if err != nil {
 
94
                return
 
95
        }
 
96
 
 
97
        pk.setFingerPrintAndKeyId()
 
98
        return
 
99
}
 
100
 
 
101
func (pk *PublicKey) setFingerPrintAndKeyId() {
 
102
        // RFC 4880, section 12.2
 
103
        fingerPrint := sha1.New()
 
104
        pk.SerializeSignaturePrefix(fingerPrint)
 
105
        pk.serializeWithoutHeaders(fingerPrint)
 
106
        copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
 
107
        pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
 
108
}
 
109
 
 
110
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
 
111
// section 5.5.2.
 
112
func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
 
113
        pk.n.bytes, pk.n.bitLength, err = readMPI(r)
 
114
        if err != nil {
 
115
                return
 
116
        }
 
117
        pk.e.bytes, pk.e.bitLength, err = readMPI(r)
 
118
        if err != nil {
 
119
                return
 
120
        }
 
121
 
 
122
        if len(pk.e.bytes) > 3 {
 
123
                err = errors.UnsupportedError("large public exponent")
 
124
                return
 
125
        }
 
126
        rsa := &rsa.PublicKey{
 
127
                N: new(big.Int).SetBytes(pk.n.bytes),
 
128
                E: 0,
 
129
        }
 
130
        for i := 0; i < len(pk.e.bytes); i++ {
 
131
                rsa.E <<= 8
 
132
                rsa.E |= int(pk.e.bytes[i])
 
133
        }
 
134
        pk.PublicKey = rsa
 
135
        return
 
136
}
 
137
 
 
138
// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
 
139
// section 5.5.2.
 
140
func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
 
141
        pk.p.bytes, pk.p.bitLength, err = readMPI(r)
 
142
        if err != nil {
 
143
                return
 
144
        }
 
145
        pk.q.bytes, pk.q.bitLength, err = readMPI(r)
 
146
        if err != nil {
 
147
                return
 
148
        }
 
149
        pk.g.bytes, pk.g.bitLength, err = readMPI(r)
 
150
        if err != nil {
 
151
                return
 
152
        }
 
153
        pk.y.bytes, pk.y.bitLength, err = readMPI(r)
 
154
        if err != nil {
 
155
                return
 
156
        }
 
157
 
 
158
        dsa := new(dsa.PublicKey)
 
159
        dsa.P = new(big.Int).SetBytes(pk.p.bytes)
 
160
        dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
 
161
        dsa.G = new(big.Int).SetBytes(pk.g.bytes)
 
162
        dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
 
163
        pk.PublicKey = dsa
 
164
        return
 
165
}
 
166
 
 
167
// parseElGamal parses ElGamal public key material from the given Reader. See
 
168
// RFC 4880, section 5.5.2.
 
169
func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
 
170
        pk.p.bytes, pk.p.bitLength, err = readMPI(r)
 
171
        if err != nil {
 
172
                return
 
173
        }
 
174
        pk.g.bytes, pk.g.bitLength, err = readMPI(r)
 
175
        if err != nil {
 
176
                return
 
177
        }
 
178
        pk.y.bytes, pk.y.bitLength, err = readMPI(r)
 
179
        if err != nil {
 
180
                return
 
181
        }
 
182
 
 
183
        elgamal := new(elgamal.PublicKey)
 
184
        elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
 
185
        elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
 
186
        elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
 
187
        pk.PublicKey = elgamal
 
188
        return
 
189
}
 
190
 
 
191
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
 
192
// The prefix is used when calculating a signature over this public key. See
 
193
// RFC 4880, section 5.2.4.
 
194
func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
 
195
        var pLength uint16
 
196
        switch pk.PubKeyAlgo {
 
197
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 
198
                pLength += 2 + uint16(len(pk.n.bytes))
 
199
                pLength += 2 + uint16(len(pk.e.bytes))
 
200
        case PubKeyAlgoDSA:
 
201
                pLength += 2 + uint16(len(pk.p.bytes))
 
202
                pLength += 2 + uint16(len(pk.q.bytes))
 
203
                pLength += 2 + uint16(len(pk.g.bytes))
 
204
                pLength += 2 + uint16(len(pk.y.bytes))
 
205
        case PubKeyAlgoElGamal:
 
206
                pLength += 2 + uint16(len(pk.p.bytes))
 
207
                pLength += 2 + uint16(len(pk.g.bytes))
 
208
                pLength += 2 + uint16(len(pk.y.bytes))
 
209
        default:
 
210
                panic("unknown public key algorithm")
 
211
        }
 
212
        pLength += 6
 
213
        h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
 
214
        return
 
215
}
 
216
 
 
217
func (pk *PublicKey) Serialize(w io.Writer) (err error) {
 
218
        length := 6 // 6 byte header
 
219
 
 
220
        switch pk.PubKeyAlgo {
 
221
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 
222
                length += 2 + len(pk.n.bytes)
 
223
                length += 2 + len(pk.e.bytes)
 
224
        case PubKeyAlgoDSA:
 
225
                length += 2 + len(pk.p.bytes)
 
226
                length += 2 + len(pk.q.bytes)
 
227
                length += 2 + len(pk.g.bytes)
 
228
                length += 2 + len(pk.y.bytes)
 
229
        case PubKeyAlgoElGamal:
 
230
                length += 2 + len(pk.p.bytes)
 
231
                length += 2 + len(pk.g.bytes)
 
232
                length += 2 + len(pk.y.bytes)
 
233
        default:
 
234
                panic("unknown public key algorithm")
 
235
        }
 
236
 
 
237
        packetType := packetTypePublicKey
 
238
        if pk.IsSubkey {
 
239
                packetType = packetTypePublicSubkey
 
240
        }
 
241
        err = serializeHeader(w, packetType, length)
 
242
        if err != nil {
 
243
                return
 
244
        }
 
245
        return pk.serializeWithoutHeaders(w)
 
246
}
 
247
 
 
248
// serializeWithoutHeaders marshals the PublicKey to w in the form of an
 
249
// OpenPGP public key packet, not including the packet header.
 
250
func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
 
251
        var buf [6]byte
 
252
        buf[0] = 4
 
253
        t := uint32(pk.CreationTime.Unix())
 
254
        buf[1] = byte(t >> 24)
 
255
        buf[2] = byte(t >> 16)
 
256
        buf[3] = byte(t >> 8)
 
257
        buf[4] = byte(t)
 
258
        buf[5] = byte(pk.PubKeyAlgo)
 
259
 
 
260
        _, err = w.Write(buf[:])
 
261
        if err != nil {
 
262
                return
 
263
        }
 
264
 
 
265
        switch pk.PubKeyAlgo {
 
266
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 
267
                return writeMPIs(w, pk.n, pk.e)
 
268
        case PubKeyAlgoDSA:
 
269
                return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
 
270
        case PubKeyAlgoElGamal:
 
271
                return writeMPIs(w, pk.p, pk.g, pk.y)
 
272
        }
 
273
        return errors.InvalidArgumentError("bad public-key algorithm")
 
274
}
 
275
 
 
276
// CanSign returns true iff this public key can generate signatures
 
277
func (pk *PublicKey) CanSign() bool {
 
278
        return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
 
279
}
 
280
 
 
281
// VerifySignature returns nil iff sig is a valid signature, made by this
 
282
// public key, of the data hashed into signed. signed is mutated by this call.
 
283
func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
 
284
        if !pk.CanSign() {
 
285
                return errors.InvalidArgumentError("public key cannot generate signatures")
 
286
        }
 
287
 
 
288
        signed.Write(sig.HashSuffix)
 
289
        hashBytes := signed.Sum(nil)
 
290
 
 
291
        if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
 
292
                return errors.SignatureError("hash tag doesn't match")
 
293
        }
 
294
 
 
295
        if pk.PubKeyAlgo != sig.PubKeyAlgo {
 
296
                return errors.InvalidArgumentError("public key and signature use different algorithms")
 
297
        }
 
298
 
 
299
        switch pk.PubKeyAlgo {
 
300
        case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
 
301
                rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
 
302
                err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
 
303
                if err != nil {
 
304
                        return errors.SignatureError("RSA verification failure")
 
305
                }
 
306
                return nil
 
307
        case PubKeyAlgoDSA:
 
308
                dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
 
309
                // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
 
310
                subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
 
311
                if len(hashBytes) > subgroupSize {
 
312
                        hashBytes = hashBytes[:subgroupSize]
 
313
                }
 
314
                if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
 
315
                        return errors.SignatureError("DSA verification failure")
 
316
                }
 
317
                return nil
 
318
        default:
 
319
                panic("shouldn't happen")
 
320
        }
 
321
        panic("unreachable")
 
322
}
 
323
 
 
324
// keySignatureHash returns a Hash of the message that needs to be signed for
 
325
// pk to assert a subkey relationship to signed.
 
326
func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err error) {
 
327
        h = sig.Hash.New()
 
328
        if h == nil {
 
329
                return nil, errors.UnsupportedError("hash function")
 
330
        }
 
331
 
 
332
        // RFC 4880, section 5.2.4
 
333
        pk.SerializeSignaturePrefix(h)
 
334
        pk.serializeWithoutHeaders(h)
 
335
        signed.SerializeSignaturePrefix(h)
 
336
        signed.serializeWithoutHeaders(h)
 
337
        return
 
338
}
 
339
 
 
340
// VerifyKeySignature returns nil iff sig is a valid signature, made by this
 
341
// public key, of signed.
 
342
func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) {
 
343
        h, err := keySignatureHash(pk, signed, sig)
 
344
        if err != nil {
 
345
                return err
 
346
        }
 
347
        return pk.VerifySignature(h, sig)
 
348
}
 
349
 
 
350
// userIdSignatureHash returns a Hash of the message that needs to be signed
 
351
// to assert that pk is a valid key for id.
 
352
func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err error) {
 
353
        h = sig.Hash.New()
 
354
        if h == nil {
 
355
                return nil, errors.UnsupportedError("hash function")
 
356
        }
 
357
 
 
358
        // RFC 4880, section 5.2.4
 
359
        pk.SerializeSignaturePrefix(h)
 
360
        pk.serializeWithoutHeaders(h)
 
361
 
 
362
        var buf [5]byte
 
363
        buf[0] = 0xb4
 
364
        buf[1] = byte(len(id) >> 24)
 
365
        buf[2] = byte(len(id) >> 16)
 
366
        buf[3] = byte(len(id) >> 8)
 
367
        buf[4] = byte(len(id))
 
368
        h.Write(buf[:])
 
369
        h.Write([]byte(id))
 
370
 
 
371
        return
 
372
}
 
373
 
 
374
// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
 
375
// public key, of id.
 
376
func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err error) {
 
377
        h, err := userIdSignatureHash(id, pk, sig)
 
378
        if err != nil {
 
379
                return err
 
380
        }
 
381
        return pk.VerifySignature(h, sig)
 
382
}
 
383
 
 
384
// KeyIdString returns the public key's fingerprint in capital hex
 
385
// (e.g. "6C7EE1B8621CC013").
 
386
func (pk *PublicKey) KeyIdString() string {
 
387
        return fmt.Sprintf("%X", pk.Fingerprint[12:20])
 
388
}
 
389
 
 
390
// KeyIdShortString returns the short form of public key's fingerprint
 
391
// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
 
392
func (pk *PublicKey) KeyIdShortString() string {
 
393
        return fmt.Sprintf("%X", pk.Fingerprint[16:20])
 
394
}
 
395
 
 
396
// A parsedMPI is used to store the contents of a big integer, along with the
 
397
// bit length that was specified in the original input. This allows the MPI to
 
398
// be reserialized exactly.
 
399
type parsedMPI struct {
 
400
        bytes     []byte
 
401
        bitLength uint16
 
402
}
 
403
 
 
404
// writeMPIs is a utility function for serializing several big integers to the
 
405
// given Writer.
 
406
func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
 
407
        for _, mpi := range mpis {
 
408
                err = writeMPI(w, mpi.bitLength, mpi.bytes)
 
409
                if err != nil {
 
410
                        return
 
411
                }
 
412
        }
 
413
        return
 
414
}
 
415
 
 
416
// BitLength returns the bit length for the given public key.
 
417
func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
 
418
        switch pk.PubKeyAlgo {
 
419
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
 
420
                bitLength = pk.n.bitLength
 
421
        case PubKeyAlgoDSA:
 
422
                bitLength = pk.p.bitLength
 
423
        case PubKeyAlgoElGamal:
 
424
                bitLength = pk.p.bitLength
 
425
        default:
 
426
                err = errors.InvalidArgumentError("bad public-key algorithm")
 
427
        }
 
428
        return
 
429
}