aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/crypto/openpgp/read.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/read.go')
-rw-r--r--vendor/golang.org/x/crypto/openpgp/read.go442
1 files changed, 442 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go
new file mode 100644
index 0000000..6ec664f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/read.go
@@ -0,0 +1,442 @@
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 openpgp implements high level operations on OpenPGP messages.
6package openpgp // import "golang.org/x/crypto/openpgp"
7
8import (
9 "crypto"
10 _ "crypto/sha256"
11 "hash"
12 "io"
13 "strconv"
14
15 "golang.org/x/crypto/openpgp/armor"
16 "golang.org/x/crypto/openpgp/errors"
17 "golang.org/x/crypto/openpgp/packet"
18)
19
20// SignatureType is the armor type for a PGP signature.
21var SignatureType = "PGP SIGNATURE"
22
23// readArmored reads an armored block with the given type.
24func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
25 block, err := armor.Decode(r)
26 if err != nil {
27 return
28 }
29
30 if block.Type != expectedType {
31 return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
32 }
33
34 return block.Body, nil
35}
36
37// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
38// signed message.
39type MessageDetails struct {
40 IsEncrypted bool // true if the message was encrypted.
41 EncryptedToKeyIds []uint64 // the list of recipient key ids.
42 IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
43 DecryptedWith Key // the private key used to decrypt the message, if any.
44 IsSigned bool // true if the message is signed.
45 SignedByKeyId uint64 // the key id of the signer, if any.
46 SignedBy *Key // the key of the signer, if available.
47 LiteralData *packet.LiteralData // the metadata of the contents
48 UnverifiedBody io.Reader // the contents of the message.
49
50 // If IsSigned is true and SignedBy is non-zero then the signature will
51 // be verified as UnverifiedBody is read. The signature cannot be
52 // checked until the whole of UnverifiedBody is read so UnverifiedBody
53 // must be consumed until EOF before the data can be trusted. Even if a
54 // message isn't signed (or the signer is unknown) the data may contain
55 // an authentication code that is only checked once UnverifiedBody has
56 // been consumed. Once EOF has been seen, the following fields are
57 // valid. (An authentication code failure is reported as a
58 // SignatureError error when reading from UnverifiedBody.)
59 SignatureError error // nil if the signature is good.
60 Signature *packet.Signature // the signature packet itself, if v4 (default)
61 SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
62
63 decrypted io.ReadCloser
64}
65
66// A PromptFunction is used as a callback by functions that may need to decrypt
67// a private key, or prompt for a passphrase. It is called with a list of
68// acceptable, encrypted private keys and a boolean that indicates whether a
69// passphrase is usable. It should either decrypt a private key or return a
70// passphrase to try. If the decrypted private key or given passphrase isn't
71// correct, the function will be called again, forever. Any error returned will
72// be passed up.
73type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
74
75// A keyEnvelopePair is used to store a private key with the envelope that
76// contains a symmetric key, encrypted with that key.
77type keyEnvelopePair struct {
78 key Key
79 encryptedKey *packet.EncryptedKey
80}
81
82// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
83// The given KeyRing should contain both public keys (for signature
84// verification) and, possibly encrypted, private keys for decrypting.
85// If config is nil, sensible defaults will be used.
86func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
87 var p packet.Packet
88
89 var symKeys []*packet.SymmetricKeyEncrypted
90 var pubKeys []keyEnvelopePair
91 var se *packet.SymmetricallyEncrypted
92
93 packets := packet.NewReader(r)
94 md = new(MessageDetails)
95 md.IsEncrypted = true
96
97 // The message, if encrypted, starts with a number of packets
98 // containing an encrypted decryption key. The decryption key is either
99 // encrypted to a public key, or with a passphrase. This loop
100 // collects these packets.
101ParsePackets:
102 for {
103 p, err = packets.Next()
104 if err != nil {
105 return nil, err
106 }
107 switch p := p.(type) {
108 case *packet.SymmetricKeyEncrypted:
109 // This packet contains the decryption key encrypted with a passphrase.
110 md.IsSymmetricallyEncrypted = true
111 symKeys = append(symKeys, p)
112 case *packet.EncryptedKey:
113 // This packet contains the decryption key encrypted to a public key.
114 md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
115 switch p.Algo {
116 case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
117 break
118 default:
119 continue
120 }
121 var keys []Key
122 if p.KeyId == 0 {
123 keys = keyring.DecryptionKeys()
124 } else {
125 keys = keyring.KeysById(p.KeyId)
126 }
127 for _, k := range keys {
128 pubKeys = append(pubKeys, keyEnvelopePair{k, p})
129 }
130 case *packet.SymmetricallyEncrypted:
131 se = p
132 break ParsePackets
133 case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
134 // This message isn't encrypted.
135 if len(symKeys) != 0 || len(pubKeys) != 0 {
136 return nil, errors.StructuralError("key material not followed by encrypted message")
137 }
138 packets.Unread(p)
139 return readSignedMessage(packets, nil, keyring)
140 }
141 }
142
143 var candidates []Key
144 var decrypted io.ReadCloser
145
146 // Now that we have the list of encrypted keys we need to decrypt at
147 // least one of them or, if we cannot, we need to call the prompt
148 // function so that it can decrypt a key or give us a passphrase.
149FindKey:
150 for {
151 // See if any of the keys already have a private key available
152 candidates = candidates[:0]
153 candidateFingerprints := make(map[string]bool)
154
155 for _, pk := range pubKeys {
156 if pk.key.PrivateKey == nil {
157 continue
158 }
159 if !pk.key.PrivateKey.Encrypted {
160 if len(pk.encryptedKey.Key) == 0 {
161 pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
162 }
163 if len(pk.encryptedKey.Key) == 0 {
164 continue
165 }
166 decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
167 if err != nil && err != errors.ErrKeyIncorrect {
168 return nil, err
169 }
170 if decrypted != nil {
171 md.DecryptedWith = pk.key
172 break FindKey
173 }
174 } else {
175 fpr := string(pk.key.PublicKey.Fingerprint[:])
176 if v := candidateFingerprints[fpr]; v {
177 continue
178 }
179 candidates = append(candidates, pk.key)
180 candidateFingerprints[fpr] = true
181 }
182 }
183
184 if len(candidates) == 0 && len(symKeys) == 0 {
185 return nil, errors.ErrKeyIncorrect
186 }
187
188 if prompt == nil {
189 return nil, errors.ErrKeyIncorrect
190 }
191
192 passphrase, err := prompt(candidates, len(symKeys) != 0)
193 if err != nil {
194 return nil, err
195 }
196
197 // Try the symmetric passphrase first
198 if len(symKeys) != 0 && passphrase != nil {
199 for _, s := range symKeys {
200 key, cipherFunc, err := s.Decrypt(passphrase)
201 if err == nil {
202 decrypted, err = se.Decrypt(cipherFunc, key)
203 if err != nil && err != errors.ErrKeyIncorrect {
204 return nil, err
205 }
206 if decrypted != nil {
207 break FindKey
208 }
209 }
210
211 }
212 }
213 }
214
215 md.decrypted = decrypted
216 if err := packets.Push(decrypted); err != nil {
217 return nil, err
218 }
219 return readSignedMessage(packets, md, keyring)
220}
221
222// readSignedMessage reads a possibly signed message if mdin is non-zero then
223// that structure is updated and returned. Otherwise a fresh MessageDetails is
224// used.
225func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
226 if mdin == nil {
227 mdin = new(MessageDetails)
228 }
229 md = mdin
230
231 var p packet.Packet
232 var h hash.Hash
233 var wrappedHash hash.Hash
234FindLiteralData:
235 for {
236 p, err = packets.Next()
237 if err != nil {
238 return nil, err
239 }
240 switch p := p.(type) {
241 case *packet.Compressed:
242 if err := packets.Push(p.Body); err != nil {
243 return nil, err
244 }
245 case *packet.OnePassSignature:
246 if !p.IsLast {
247 return nil, errors.UnsupportedError("nested signatures")
248 }
249
250 h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
251 if err != nil {
252 md = nil
253 return
254 }
255
256 md.IsSigned = true
257 md.SignedByKeyId = p.KeyId
258 keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
259 if len(keys) > 0 {
260 md.SignedBy = &keys[0]
261 }
262 case *packet.LiteralData:
263 md.LiteralData = p
264 break FindLiteralData
265 }
266 }
267
268 if md.SignedBy != nil {
269 md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
270 } else if md.decrypted != nil {
271 md.UnverifiedBody = checkReader{md}
272 } else {
273 md.UnverifiedBody = md.LiteralData.Body
274 }
275
276 return md, nil
277}
278
279// hashForSignature returns a pair of hashes that can be used to verify a
280// signature. The signature may specify that the contents of the signed message
281// should be preprocessed (i.e. to normalize line endings). Thus this function
282// returns two hashes. The second should be used to hash the message itself and
283// performs any needed preprocessing.
284func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
285 if !hashId.Available() {
286 return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
287 }
288 h := hashId.New()
289
290 switch sigType {
291 case packet.SigTypeBinary:
292 return h, h, nil
293 case packet.SigTypeText:
294 return h, NewCanonicalTextHash(h), nil
295 }
296
297 return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
298}
299
300// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
301// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
302// MDC checks.
303type checkReader struct {
304 md *MessageDetails
305}
306
307func (cr checkReader) Read(buf []byte) (n int, err error) {
308 n, err = cr.md.LiteralData.Body.Read(buf)
309 if err == io.EOF {
310 mdcErr := cr.md.decrypted.Close()
311 if mdcErr != nil {
312 err = mdcErr
313 }
314 }
315 return
316}
317
318// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
319// the data as it is read. When it sees an EOF from the underlying io.Reader
320// it parses and checks a trailing Signature packet and triggers any MDC checks.
321type signatureCheckReader struct {
322 packets *packet.Reader
323 h, wrappedHash hash.Hash
324 md *MessageDetails
325}
326
327func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
328 n, err = scr.md.LiteralData.Body.Read(buf)
329 scr.wrappedHash.Write(buf[:n])
330 if err == io.EOF {
331 var p packet.Packet
332 p, scr.md.SignatureError = scr.packets.Next()
333 if scr.md.SignatureError != nil {
334 return
335 }
336
337 var ok bool
338 if scr.md.Signature, ok = p.(*packet.Signature); ok {
339 scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
340 } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
341 scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
342 } else {
343 scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
344 return
345 }
346
347 // The SymmetricallyEncrypted packet, if any, might have an
348 // unsigned hash of its own. In order to check this we need to
349 // close that Reader.
350 if scr.md.decrypted != nil {
351 mdcErr := scr.md.decrypted.Close()
352 if mdcErr != nil {
353 err = mdcErr
354 }
355 }
356 }
357 return
358}
359
360// CheckDetachedSignature takes a signed file and a detached signature and
361// returns the signer if the signature is valid. If the signer isn't known,
362// ErrUnknownIssuer is returned.
363func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
364 var issuerKeyId uint64
365 var hashFunc crypto.Hash
366 var sigType packet.SignatureType
367 var keys []Key
368 var p packet.Packet
369
370 packets := packet.NewReader(signature)
371 for {
372 p, err = packets.Next()
373 if err == io.EOF {
374 return nil, errors.ErrUnknownIssuer
375 }
376 if err != nil {
377 return nil, err
378 }
379
380 switch sig := p.(type) {
381 case *packet.Signature:
382 if sig.IssuerKeyId == nil {
383 return nil, errors.StructuralError("signature doesn't have an issuer")
384 }
385 issuerKeyId = *sig.IssuerKeyId
386 hashFunc = sig.Hash
387 sigType = sig.SigType
388 case *packet.SignatureV3:
389 issuerKeyId = sig.IssuerKeyId
390 hashFunc = sig.Hash
391 sigType = sig.SigType
392 default:
393 return nil, errors.StructuralError("non signature packet found")
394 }
395
396 keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
397 if len(keys) > 0 {
398 break
399 }
400 }
401
402 if len(keys) == 0 {
403 panic("unreachable")
404 }
405
406 h, wrappedHash, err := hashForSignature(hashFunc, sigType)
407 if err != nil {
408 return nil, err
409 }
410
411 if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
412 return nil, err
413 }
414
415 for _, key := range keys {
416 switch sig := p.(type) {
417 case *packet.Signature:
418 err = key.PublicKey.VerifySignature(h, sig)
419 case *packet.SignatureV3:
420 err = key.PublicKey.VerifySignatureV3(h, sig)
421 default:
422 panic("unreachable")
423 }
424
425 if err == nil {
426 return key.Entity, nil
427 }
428 }
429
430 return nil, err
431}
432
433// CheckArmoredDetachedSignature performs the same actions as
434// CheckDetachedSignature but expects the signature to be armored.
435func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
436 body, err := readArmored(signature, SignatureType)
437 if err != nil {
438 return
439 }
440
441 return CheckDetachedSignature(keyring, signed, body)
442}