]>
Commit | Line | Data |
---|---|---|
c680a8e1 RS |
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 | "bytes" | |
9 | "crypto" | |
10 | "crypto/dsa" | |
11 | "crypto/ecdsa" | |
12 | "crypto/elliptic" | |
13 | "crypto/rsa" | |
14 | "crypto/sha1" | |
15 | _ "crypto/sha256" | |
16 | _ "crypto/sha512" | |
17 | "encoding/binary" | |
18 | "fmt" | |
19 | "hash" | |
20 | "io" | |
21 | "math/big" | |
22 | "strconv" | |
23 | "time" | |
24 | ||
25 | "golang.org/x/crypto/openpgp/elgamal" | |
26 | "golang.org/x/crypto/openpgp/errors" | |
27 | ) | |
28 | ||
29 | var ( | |
30 | // NIST curve P-256 | |
31 | oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} | |
32 | // NIST curve P-384 | |
33 | oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} | |
34 | // NIST curve P-521 | |
35 | oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} | |
36 | ) | |
37 | ||
38 | const maxOIDLength = 8 | |
39 | ||
40 | // ecdsaKey stores the algorithm-specific fields for ECDSA keys. | |
41 | // as defined in RFC 6637, Section 9. | |
42 | type ecdsaKey struct { | |
43 | // oid contains the OID byte sequence identifying the elliptic curve used | |
44 | oid []byte | |
45 | // p contains the elliptic curve point that represents the public key | |
46 | p parsedMPI | |
47 | } | |
48 | ||
49 | // parseOID reads the OID for the curve as defined in RFC 6637, Section 9. | |
50 | func parseOID(r io.Reader) (oid []byte, err error) { | |
51 | buf := make([]byte, maxOIDLength) | |
52 | if _, err = readFull(r, buf[:1]); err != nil { | |
53 | return | |
54 | } | |
55 | oidLen := buf[0] | |
56 | if int(oidLen) > len(buf) { | |
57 | err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) | |
58 | return | |
59 | } | |
60 | oid = buf[:oidLen] | |
61 | _, err = readFull(r, oid) | |
62 | return | |
63 | } | |
64 | ||
65 | func (f *ecdsaKey) parse(r io.Reader) (err error) { | |
66 | if f.oid, err = parseOID(r); err != nil { | |
67 | return err | |
68 | } | |
69 | f.p.bytes, f.p.bitLength, err = readMPI(r) | |
70 | return | |
71 | } | |
72 | ||
73 | func (f *ecdsaKey) serialize(w io.Writer) (err error) { | |
74 | buf := make([]byte, maxOIDLength+1) | |
75 | buf[0] = byte(len(f.oid)) | |
76 | copy(buf[1:], f.oid) | |
77 | if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { | |
78 | return | |
79 | } | |
80 | return writeMPIs(w, f.p) | |
81 | } | |
82 | ||
83 | func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { | |
84 | var c elliptic.Curve | |
85 | if bytes.Equal(f.oid, oidCurveP256) { | |
86 | c = elliptic.P256() | |
87 | } else if bytes.Equal(f.oid, oidCurveP384) { | |
88 | c = elliptic.P384() | |
89 | } else if bytes.Equal(f.oid, oidCurveP521) { | |
90 | c = elliptic.P521() | |
91 | } else { | |
92 | return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) | |
93 | } | |
94 | x, y := elliptic.Unmarshal(c, f.p.bytes) | |
95 | if x == nil { | |
96 | return nil, errors.UnsupportedError("failed to parse EC point") | |
97 | } | |
98 | return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil | |
99 | } | |
100 | ||
101 | func (f *ecdsaKey) byteLen() int { | |
102 | return 1 + len(f.oid) + 2 + len(f.p.bytes) | |
103 | } | |
104 | ||
105 | type kdfHashFunction byte | |
106 | type kdfAlgorithm byte | |
107 | ||
108 | // ecdhKdf stores key derivation function parameters | |
109 | // used for ECDH encryption. See RFC 6637, Section 9. | |
110 | type ecdhKdf struct { | |
111 | KdfHash kdfHashFunction | |
112 | KdfAlgo kdfAlgorithm | |
113 | } | |
114 | ||
115 | func (f *ecdhKdf) parse(r io.Reader) (err error) { | |
116 | buf := make([]byte, 1) | |
117 | if _, err = readFull(r, buf); err != nil { | |
118 | return | |
119 | } | |
120 | kdfLen := int(buf[0]) | |
121 | if kdfLen < 3 { | |
122 | return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) | |
123 | } | |
124 | buf = make([]byte, kdfLen) | |
125 | if _, err = readFull(r, buf); err != nil { | |
126 | return | |
127 | } | |
128 | reserved := int(buf[0]) | |
129 | f.KdfHash = kdfHashFunction(buf[1]) | |
130 | f.KdfAlgo = kdfAlgorithm(buf[2]) | |
131 | if reserved != 0x01 { | |
132 | return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) | |
133 | } | |
134 | return | |
135 | } | |
136 | ||
137 | func (f *ecdhKdf) serialize(w io.Writer) (err error) { | |
138 | buf := make([]byte, 4) | |
139 | // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. | |
140 | buf[0] = byte(0x03) // Length of the following fields | |
141 | buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now | |
142 | buf[2] = byte(f.KdfHash) | |
143 | buf[3] = byte(f.KdfAlgo) | |
144 | _, err = w.Write(buf[:]) | |
145 | return | |
146 | } | |
147 | ||
148 | func (f *ecdhKdf) byteLen() int { | |
149 | return 4 | |
150 | } | |
151 | ||
152 | // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. | |
153 | type PublicKey struct { | |
154 | CreationTime time.Time | |
155 | PubKeyAlgo PublicKeyAlgorithm | |
156 | PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey | |
157 | Fingerprint [20]byte | |
158 | KeyId uint64 | |
159 | IsSubkey bool | |
160 | ||
161 | n, e, p, q, g, y parsedMPI | |
162 | ||
163 | // RFC 6637 fields | |
164 | ec *ecdsaKey | |
165 | ecdh *ecdhKdf | |
166 | } | |
167 | ||
168 | // signingKey provides a convenient abstraction over signature verification | |
169 | // for v3 and v4 public keys. | |
170 | type signingKey interface { | |
171 | SerializeSignaturePrefix(io.Writer) | |
172 | serializeWithoutHeaders(io.Writer) error | |
173 | } | |
174 | ||
175 | func fromBig(n *big.Int) parsedMPI { | |
176 | return parsedMPI{ | |
177 | bytes: n.Bytes(), | |
178 | bitLength: uint16(n.BitLen()), | |
179 | } | |
180 | } | |
181 | ||
182 | // NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. | |
183 | func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { | |
184 | pk := &PublicKey{ | |
185 | CreationTime: creationTime, | |
186 | PubKeyAlgo: PubKeyAlgoRSA, | |
187 | PublicKey: pub, | |
188 | n: fromBig(pub.N), | |
189 | e: fromBig(big.NewInt(int64(pub.E))), | |
190 | } | |
191 | ||
192 | pk.setFingerPrintAndKeyId() | |
193 | return pk | |
194 | } | |
195 | ||
196 | // NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. | |
197 | func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { | |
198 | pk := &PublicKey{ | |
199 | CreationTime: creationTime, | |
200 | PubKeyAlgo: PubKeyAlgoDSA, | |
201 | PublicKey: pub, | |
202 | p: fromBig(pub.P), | |
203 | q: fromBig(pub.Q), | |
204 | g: fromBig(pub.G), | |
205 | y: fromBig(pub.Y), | |
206 | } | |
207 | ||
208 | pk.setFingerPrintAndKeyId() | |
209 | return pk | |
210 | } | |
211 | ||
212 | // NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. | |
213 | func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { | |
214 | pk := &PublicKey{ | |
215 | CreationTime: creationTime, | |
216 | PubKeyAlgo: PubKeyAlgoElGamal, | |
217 | PublicKey: pub, | |
218 | p: fromBig(pub.P), | |
219 | g: fromBig(pub.G), | |
220 | y: fromBig(pub.Y), | |
221 | } | |
222 | ||
223 | pk.setFingerPrintAndKeyId() | |
224 | return pk | |
225 | } | |
226 | ||
227 | func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { | |
228 | pk := &PublicKey{ | |
229 | CreationTime: creationTime, | |
230 | PubKeyAlgo: PubKeyAlgoECDSA, | |
231 | PublicKey: pub, | |
232 | ec: new(ecdsaKey), | |
233 | } | |
234 | ||
235 | switch pub.Curve { | |
236 | case elliptic.P256(): | |
237 | pk.ec.oid = oidCurveP256 | |
238 | case elliptic.P384(): | |
239 | pk.ec.oid = oidCurveP384 | |
240 | case elliptic.P521(): | |
241 | pk.ec.oid = oidCurveP521 | |
242 | default: | |
243 | panic("unknown elliptic curve") | |
244 | } | |
245 | ||
246 | pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) | |
107c1cdb ND |
247 | |
248 | // The bit length is 3 (for the 0x04 specifying an uncompressed key) | |
249 | // plus two field elements (for x and y), which are rounded up to the | |
250 | // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 | |
251 | fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 | |
252 | pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) | |
c680a8e1 RS |
253 | |
254 | pk.setFingerPrintAndKeyId() | |
255 | return pk | |
256 | } | |
257 | ||
258 | func (pk *PublicKey) parse(r io.Reader) (err error) { | |
259 | // RFC 4880, section 5.5.2 | |
260 | var buf [6]byte | |
261 | _, err = readFull(r, buf[:]) | |
262 | if err != nil { | |
263 | return | |
264 | } | |
265 | if buf[0] != 4 { | |
266 | return errors.UnsupportedError("public key version") | |
267 | } | |
268 | pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) | |
269 | pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) | |
270 | switch pk.PubKeyAlgo { | |
271 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
272 | err = pk.parseRSA(r) | |
273 | case PubKeyAlgoDSA: | |
274 | err = pk.parseDSA(r) | |
275 | case PubKeyAlgoElGamal: | |
276 | err = pk.parseElGamal(r) | |
277 | case PubKeyAlgoECDSA: | |
278 | pk.ec = new(ecdsaKey) | |
279 | if err = pk.ec.parse(r); err != nil { | |
280 | return err | |
281 | } | |
282 | pk.PublicKey, err = pk.ec.newECDSA() | |
283 | case PubKeyAlgoECDH: | |
284 | pk.ec = new(ecdsaKey) | |
285 | if err = pk.ec.parse(r); err != nil { | |
286 | return | |
287 | } | |
288 | pk.ecdh = new(ecdhKdf) | |
289 | if err = pk.ecdh.parse(r); err != nil { | |
290 | return | |
291 | } | |
292 | // The ECDH key is stored in an ecdsa.PublicKey for convenience. | |
293 | pk.PublicKey, err = pk.ec.newECDSA() | |
294 | default: | |
295 | err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) | |
296 | } | |
297 | if err != nil { | |
298 | return | |
299 | } | |
300 | ||
301 | pk.setFingerPrintAndKeyId() | |
302 | return | |
303 | } | |
304 | ||
305 | func (pk *PublicKey) setFingerPrintAndKeyId() { | |
306 | // RFC 4880, section 12.2 | |
307 | fingerPrint := sha1.New() | |
308 | pk.SerializeSignaturePrefix(fingerPrint) | |
309 | pk.serializeWithoutHeaders(fingerPrint) | |
310 | copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) | |
311 | pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) | |
312 | } | |
313 | ||
314 | // parseRSA parses RSA public key material from the given Reader. See RFC 4880, | |
315 | // section 5.5.2. | |
316 | func (pk *PublicKey) parseRSA(r io.Reader) (err error) { | |
317 | pk.n.bytes, pk.n.bitLength, err = readMPI(r) | |
318 | if err != nil { | |
319 | return | |
320 | } | |
321 | pk.e.bytes, pk.e.bitLength, err = readMPI(r) | |
322 | if err != nil { | |
323 | return | |
324 | } | |
325 | ||
326 | if len(pk.e.bytes) > 3 { | |
327 | err = errors.UnsupportedError("large public exponent") | |
328 | return | |
329 | } | |
330 | rsa := &rsa.PublicKey{ | |
331 | N: new(big.Int).SetBytes(pk.n.bytes), | |
332 | E: 0, | |
333 | } | |
334 | for i := 0; i < len(pk.e.bytes); i++ { | |
335 | rsa.E <<= 8 | |
336 | rsa.E |= int(pk.e.bytes[i]) | |
337 | } | |
338 | pk.PublicKey = rsa | |
339 | return | |
340 | } | |
341 | ||
342 | // parseDSA parses DSA public key material from the given Reader. See RFC 4880, | |
343 | // section 5.5.2. | |
344 | func (pk *PublicKey) parseDSA(r io.Reader) (err error) { | |
345 | pk.p.bytes, pk.p.bitLength, err = readMPI(r) | |
346 | if err != nil { | |
347 | return | |
348 | } | |
349 | pk.q.bytes, pk.q.bitLength, err = readMPI(r) | |
350 | if err != nil { | |
351 | return | |
352 | } | |
353 | pk.g.bytes, pk.g.bitLength, err = readMPI(r) | |
354 | if err != nil { | |
355 | return | |
356 | } | |
357 | pk.y.bytes, pk.y.bitLength, err = readMPI(r) | |
358 | if err != nil { | |
359 | return | |
360 | } | |
361 | ||
362 | dsa := new(dsa.PublicKey) | |
363 | dsa.P = new(big.Int).SetBytes(pk.p.bytes) | |
364 | dsa.Q = new(big.Int).SetBytes(pk.q.bytes) | |
365 | dsa.G = new(big.Int).SetBytes(pk.g.bytes) | |
366 | dsa.Y = new(big.Int).SetBytes(pk.y.bytes) | |
367 | pk.PublicKey = dsa | |
368 | return | |
369 | } | |
370 | ||
371 | // parseElGamal parses ElGamal public key material from the given Reader. See | |
372 | // RFC 4880, section 5.5.2. | |
373 | func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { | |
374 | pk.p.bytes, pk.p.bitLength, err = readMPI(r) | |
375 | if err != nil { | |
376 | return | |
377 | } | |
378 | pk.g.bytes, pk.g.bitLength, err = readMPI(r) | |
379 | if err != nil { | |
380 | return | |
381 | } | |
382 | pk.y.bytes, pk.y.bitLength, err = readMPI(r) | |
383 | if err != nil { | |
384 | return | |
385 | } | |
386 | ||
387 | elgamal := new(elgamal.PublicKey) | |
388 | elgamal.P = new(big.Int).SetBytes(pk.p.bytes) | |
389 | elgamal.G = new(big.Int).SetBytes(pk.g.bytes) | |
390 | elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) | |
391 | pk.PublicKey = elgamal | |
392 | return | |
393 | } | |
394 | ||
395 | // SerializeSignaturePrefix writes the prefix for this public key to the given Writer. | |
396 | // The prefix is used when calculating a signature over this public key. See | |
397 | // RFC 4880, section 5.2.4. | |
398 | func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { | |
399 | var pLength uint16 | |
400 | switch pk.PubKeyAlgo { | |
401 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
402 | pLength += 2 + uint16(len(pk.n.bytes)) | |
403 | pLength += 2 + uint16(len(pk.e.bytes)) | |
404 | case PubKeyAlgoDSA: | |
405 | pLength += 2 + uint16(len(pk.p.bytes)) | |
406 | pLength += 2 + uint16(len(pk.q.bytes)) | |
407 | pLength += 2 + uint16(len(pk.g.bytes)) | |
408 | pLength += 2 + uint16(len(pk.y.bytes)) | |
409 | case PubKeyAlgoElGamal: | |
410 | pLength += 2 + uint16(len(pk.p.bytes)) | |
411 | pLength += 2 + uint16(len(pk.g.bytes)) | |
412 | pLength += 2 + uint16(len(pk.y.bytes)) | |
413 | case PubKeyAlgoECDSA: | |
414 | pLength += uint16(pk.ec.byteLen()) | |
415 | case PubKeyAlgoECDH: | |
416 | pLength += uint16(pk.ec.byteLen()) | |
417 | pLength += uint16(pk.ecdh.byteLen()) | |
418 | default: | |
419 | panic("unknown public key algorithm") | |
420 | } | |
421 | pLength += 6 | |
422 | h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) | |
423 | return | |
424 | } | |
425 | ||
426 | func (pk *PublicKey) Serialize(w io.Writer) (err error) { | |
427 | length := 6 // 6 byte header | |
428 | ||
429 | switch pk.PubKeyAlgo { | |
430 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
431 | length += 2 + len(pk.n.bytes) | |
432 | length += 2 + len(pk.e.bytes) | |
433 | case PubKeyAlgoDSA: | |
434 | length += 2 + len(pk.p.bytes) | |
435 | length += 2 + len(pk.q.bytes) | |
436 | length += 2 + len(pk.g.bytes) | |
437 | length += 2 + len(pk.y.bytes) | |
438 | case PubKeyAlgoElGamal: | |
439 | length += 2 + len(pk.p.bytes) | |
440 | length += 2 + len(pk.g.bytes) | |
441 | length += 2 + len(pk.y.bytes) | |
442 | case PubKeyAlgoECDSA: | |
443 | length += pk.ec.byteLen() | |
444 | case PubKeyAlgoECDH: | |
445 | length += pk.ec.byteLen() | |
446 | length += pk.ecdh.byteLen() | |
447 | default: | |
448 | panic("unknown public key algorithm") | |
449 | } | |
450 | ||
451 | packetType := packetTypePublicKey | |
452 | if pk.IsSubkey { | |
453 | packetType = packetTypePublicSubkey | |
454 | } | |
455 | err = serializeHeader(w, packetType, length) | |
456 | if err != nil { | |
457 | return | |
458 | } | |
459 | return pk.serializeWithoutHeaders(w) | |
460 | } | |
461 | ||
462 | // serializeWithoutHeaders marshals the PublicKey to w in the form of an | |
463 | // OpenPGP public key packet, not including the packet header. | |
464 | func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { | |
465 | var buf [6]byte | |
466 | buf[0] = 4 | |
467 | t := uint32(pk.CreationTime.Unix()) | |
468 | buf[1] = byte(t >> 24) | |
469 | buf[2] = byte(t >> 16) | |
470 | buf[3] = byte(t >> 8) | |
471 | buf[4] = byte(t) | |
472 | buf[5] = byte(pk.PubKeyAlgo) | |
473 | ||
474 | _, err = w.Write(buf[:]) | |
475 | if err != nil { | |
476 | return | |
477 | } | |
478 | ||
479 | switch pk.PubKeyAlgo { | |
480 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
481 | return writeMPIs(w, pk.n, pk.e) | |
482 | case PubKeyAlgoDSA: | |
483 | return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) | |
484 | case PubKeyAlgoElGamal: | |
485 | return writeMPIs(w, pk.p, pk.g, pk.y) | |
486 | case PubKeyAlgoECDSA: | |
487 | return pk.ec.serialize(w) | |
488 | case PubKeyAlgoECDH: | |
489 | if err = pk.ec.serialize(w); err != nil { | |
490 | return | |
491 | } | |
492 | return pk.ecdh.serialize(w) | |
493 | } | |
494 | return errors.InvalidArgumentError("bad public-key algorithm") | |
495 | } | |
496 | ||
497 | // CanSign returns true iff this public key can generate signatures | |
498 | func (pk *PublicKey) CanSign() bool { | |
499 | return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal | |
500 | } | |
501 | ||
502 | // VerifySignature returns nil iff sig is a valid signature, made by this | |
503 | // public key, of the data hashed into signed. signed is mutated by this call. | |
504 | func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { | |
505 | if !pk.CanSign() { | |
506 | return errors.InvalidArgumentError("public key cannot generate signatures") | |
507 | } | |
508 | ||
509 | signed.Write(sig.HashSuffix) | |
510 | hashBytes := signed.Sum(nil) | |
511 | ||
512 | if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { | |
513 | return errors.SignatureError("hash tag doesn't match") | |
514 | } | |
515 | ||
516 | if pk.PubKeyAlgo != sig.PubKeyAlgo { | |
517 | return errors.InvalidArgumentError("public key and signature use different algorithms") | |
518 | } | |
519 | ||
520 | switch pk.PubKeyAlgo { | |
521 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | |
522 | rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) | |
107c1cdb | 523 | err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) |
c680a8e1 RS |
524 | if err != nil { |
525 | return errors.SignatureError("RSA verification failure") | |
526 | } | |
527 | return nil | |
528 | case PubKeyAlgoDSA: | |
529 | dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) | |
530 | // Need to truncate hashBytes to match FIPS 186-3 section 4.6. | |
531 | subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 | |
532 | if len(hashBytes) > subgroupSize { | |
533 | hashBytes = hashBytes[:subgroupSize] | |
534 | } | |
535 | if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { | |
536 | return errors.SignatureError("DSA verification failure") | |
537 | } | |
538 | return nil | |
539 | case PubKeyAlgoECDSA: | |
540 | ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) | |
541 | if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { | |
542 | return errors.SignatureError("ECDSA verification failure") | |
543 | } | |
544 | return nil | |
545 | default: | |
546 | return errors.SignatureError("Unsupported public key algorithm used in signature") | |
547 | } | |
548 | } | |
549 | ||
550 | // VerifySignatureV3 returns nil iff sig is a valid signature, made by this | |
551 | // public key, of the data hashed into signed. signed is mutated by this call. | |
552 | func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { | |
553 | if !pk.CanSign() { | |
554 | return errors.InvalidArgumentError("public key cannot generate signatures") | |
555 | } | |
556 | ||
557 | suffix := make([]byte, 5) | |
558 | suffix[0] = byte(sig.SigType) | |
559 | binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) | |
560 | signed.Write(suffix) | |
561 | hashBytes := signed.Sum(nil) | |
562 | ||
563 | if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { | |
564 | return errors.SignatureError("hash tag doesn't match") | |
565 | } | |
566 | ||
567 | if pk.PubKeyAlgo != sig.PubKeyAlgo { | |
568 | return errors.InvalidArgumentError("public key and signature use different algorithms") | |
569 | } | |
570 | ||
571 | switch pk.PubKeyAlgo { | |
572 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | |
573 | rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) | |
107c1cdb | 574 | if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { |
c680a8e1 RS |
575 | return errors.SignatureError("RSA verification failure") |
576 | } | |
577 | return | |
578 | case PubKeyAlgoDSA: | |
579 | dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) | |
580 | // Need to truncate hashBytes to match FIPS 186-3 section 4.6. | |
581 | subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 | |
582 | if len(hashBytes) > subgroupSize { | |
583 | hashBytes = hashBytes[:subgroupSize] | |
584 | } | |
585 | if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { | |
586 | return errors.SignatureError("DSA verification failure") | |
587 | } | |
588 | return nil | |
589 | default: | |
590 | panic("shouldn't happen") | |
591 | } | |
592 | } | |
593 | ||
594 | // keySignatureHash returns a Hash of the message that needs to be signed for | |
595 | // pk to assert a subkey relationship to signed. | |
596 | func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { | |
597 | if !hashFunc.Available() { | |
598 | return nil, errors.UnsupportedError("hash function") | |
599 | } | |
600 | h = hashFunc.New() | |
601 | ||
602 | // RFC 4880, section 5.2.4 | |
603 | pk.SerializeSignaturePrefix(h) | |
604 | pk.serializeWithoutHeaders(h) | |
605 | signed.SerializeSignaturePrefix(h) | |
606 | signed.serializeWithoutHeaders(h) | |
607 | return | |
608 | } | |
609 | ||
610 | // VerifyKeySignature returns nil iff sig is a valid signature, made by this | |
611 | // public key, of signed. | |
612 | func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { | |
613 | h, err := keySignatureHash(pk, signed, sig.Hash) | |
614 | if err != nil { | |
615 | return err | |
616 | } | |
617 | if err = pk.VerifySignature(h, sig); err != nil { | |
618 | return err | |
619 | } | |
620 | ||
621 | if sig.FlagSign { | |
622 | // Signing subkeys must be cross-signed. See | |
623 | // https://www.gnupg.org/faq/subkey-cross-certify.html. | |
624 | if sig.EmbeddedSignature == nil { | |
625 | return errors.StructuralError("signing subkey is missing cross-signature") | |
626 | } | |
627 | // Verify the cross-signature. This is calculated over the same | |
628 | // data as the main signature, so we cannot just recursively | |
629 | // call signed.VerifyKeySignature(...) | |
630 | if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { | |
631 | return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) | |
632 | } | |
633 | if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { | |
634 | return errors.StructuralError("error while verifying cross-signature: " + err.Error()) | |
635 | } | |
636 | } | |
637 | ||
638 | return nil | |
639 | } | |
640 | ||
641 | func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { | |
642 | if !hashFunc.Available() { | |
643 | return nil, errors.UnsupportedError("hash function") | |
644 | } | |
645 | h = hashFunc.New() | |
646 | ||
647 | // RFC 4880, section 5.2.4 | |
648 | pk.SerializeSignaturePrefix(h) | |
649 | pk.serializeWithoutHeaders(h) | |
650 | ||
651 | return | |
652 | } | |
653 | ||
654 | // VerifyRevocationSignature returns nil iff sig is a valid signature, made by this | |
655 | // public key. | |
656 | func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { | |
657 | h, err := keyRevocationHash(pk, sig.Hash) | |
658 | if err != nil { | |
659 | return err | |
660 | } | |
661 | return pk.VerifySignature(h, sig) | |
662 | } | |
663 | ||
664 | // userIdSignatureHash returns a Hash of the message that needs to be signed | |
665 | // to assert that pk is a valid key for id. | |
666 | func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { | |
667 | if !hashFunc.Available() { | |
668 | return nil, errors.UnsupportedError("hash function") | |
669 | } | |
670 | h = hashFunc.New() | |
671 | ||
672 | // RFC 4880, section 5.2.4 | |
673 | pk.SerializeSignaturePrefix(h) | |
674 | pk.serializeWithoutHeaders(h) | |
675 | ||
676 | var buf [5]byte | |
677 | buf[0] = 0xb4 | |
678 | buf[1] = byte(len(id) >> 24) | |
679 | buf[2] = byte(len(id) >> 16) | |
680 | buf[3] = byte(len(id) >> 8) | |
681 | buf[4] = byte(len(id)) | |
682 | h.Write(buf[:]) | |
683 | h.Write([]byte(id)) | |
684 | ||
685 | return | |
686 | } | |
687 | ||
688 | // VerifyUserIdSignature returns nil iff sig is a valid signature, made by this | |
689 | // public key, that id is the identity of pub. | |
690 | func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { | |
691 | h, err := userIdSignatureHash(id, pub, sig.Hash) | |
692 | if err != nil { | |
693 | return err | |
694 | } | |
695 | return pk.VerifySignature(h, sig) | |
696 | } | |
697 | ||
698 | // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this | |
699 | // public key, that id is the identity of pub. | |
700 | func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { | |
701 | h, err := userIdSignatureV3Hash(id, pub, sig.Hash) | |
702 | if err != nil { | |
703 | return err | |
704 | } | |
705 | return pk.VerifySignatureV3(h, sig) | |
706 | } | |
707 | ||
708 | // KeyIdString returns the public key's fingerprint in capital hex | |
709 | // (e.g. "6C7EE1B8621CC013"). | |
710 | func (pk *PublicKey) KeyIdString() string { | |
711 | return fmt.Sprintf("%X", pk.Fingerprint[12:20]) | |
712 | } | |
713 | ||
714 | // KeyIdShortString returns the short form of public key's fingerprint | |
715 | // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). | |
716 | func (pk *PublicKey) KeyIdShortString() string { | |
717 | return fmt.Sprintf("%X", pk.Fingerprint[16:20]) | |
718 | } | |
719 | ||
720 | // A parsedMPI is used to store the contents of a big integer, along with the | |
721 | // bit length that was specified in the original input. This allows the MPI to | |
722 | // be reserialized exactly. | |
723 | type parsedMPI struct { | |
724 | bytes []byte | |
725 | bitLength uint16 | |
726 | } | |
727 | ||
728 | // writeMPIs is a utility function for serializing several big integers to the | |
729 | // given Writer. | |
730 | func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { | |
731 | for _, mpi := range mpis { | |
732 | err = writeMPI(w, mpi.bitLength, mpi.bytes) | |
733 | if err != nil { | |
734 | return | |
735 | } | |
736 | } | |
737 | return | |
738 | } | |
739 | ||
740 | // BitLength returns the bit length for the given public key. | |
741 | func (pk *PublicKey) BitLength() (bitLength uint16, err error) { | |
742 | switch pk.PubKeyAlgo { | |
743 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
744 | bitLength = pk.n.bitLength | |
745 | case PubKeyAlgoDSA: | |
746 | bitLength = pk.p.bitLength | |
747 | case PubKeyAlgoElGamal: | |
748 | bitLength = pk.p.bitLength | |
749 | default: | |
750 | err = errors.InvalidArgumentError("bad public-key algorithm") | |
751 | } | |
752 | return | |
753 | } |