/
verify_reader.go
148 lines (130 loc) · 4.8 KB
/
verify_reader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package crypto
import (
"io"
openpgp "github.com/ProtonMail/go-crypto/openpgp/v2"
"github.com/pkg/errors"
)
// VerifyDataReader is used for reading data that should be verified with a signature.
// It further contains additional information about the parsed pgp message where the read
// data stems from.
type VerifyDataReader struct {
details *openpgp.MessageDetails
internalReader Reader
verifyKeyRing *KeyRing
verifyTime int64
disableTimeCheck bool
readAll bool
verificationContext *VerificationContext
}
// GetMetadata returns the metadata of the literal data packet that
// this reader reads from. Can be nil, if the data is not read from
// a literal data packet.
func (msg *VerifyDataReader) GetMetadata() *LiteralMetadata {
if msg.details.LiteralData == nil {
return nil
}
return &LiteralMetadata{
filename: msg.details.LiteralData.FileName,
isUTF8: !msg.details.LiteralData.IsBinary,
ModTime: int64(msg.details.LiteralData.Time),
}
}
// Read is used read data from the pgp message.
// Makes VerifyDataReader implement the Reader interface.
func (msg *VerifyDataReader) Read(b []byte) (n int, err error) {
n, err = msg.internalReader.Read(b)
if errors.Is(err, io.EOF) {
msg.readAll = true
}
return
}
// VerifySignature is used to verify that the embedded signatures are valid.
// This method needs to be called once all the data has been read.
// It will return an error if the signature is invalid, no verifying keys are accessible,
// or if the message hasn't been read entirely.
func (msg *VerifyDataReader) VerifySignature() (result *VerifyResult, err error) {
if !msg.readAll {
return nil, errors.New("gopenpgp: can't verify the signature until the message reader has been read entirely")
}
return createVerifyResult(msg.details, msg.verifyKeyRing, msg.verificationContext, msg.verifyTime, msg.disableTimeCheck)
}
// ReadAll reads all plaintext data from the reader
// and returns it as a byte slice.
func (msg *VerifyDataReader) ReadAll() (plaintext []byte, err error) {
return io.ReadAll(msg)
}
// DiscardAll reads all data from the reader and discards it.
func (msg *VerifyDataReader) DiscardAll() (err error) {
_, err = io.Copy(io.Discard, msg)
return err
}
// DiscardAllAndVerifySignature reads all plaintext data from the reader but discards it.
// Returns a verification result for signature verification on the read data.
func (msg *VerifyDataReader) DiscardAllAndVerifySignature() (vr *VerifyResult, err error) {
err = msg.DiscardAll()
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: discarding data from reader failed")
}
return msg.VerifySignature()
}
// ReadAllAndVerifySignature reads all plaintext data from the reader
// and tries to verify the signatures included in the message.
// Returns the data in a VerifiedDataResult struct, which can be checked for signature errors.
func (msg *VerifyDataReader) ReadAllAndVerifySignature() (*VerifiedDataResult, error) {
plaintext, err := msg.ReadAll()
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: reading all data from reader failed")
}
verifyResult, err := msg.VerifySignature()
return &VerifiedDataResult{
VerifyResult: *verifyResult,
data: plaintext,
metadata: msg.GetMetadata(),
cachedSessionKey: msg.SessionKey(),
}, err
}
// SessionKey returns the session key the data is decrypted with.
// Returns nil, if this reader does not read from an encrypted message or
// session key caching was not enabled.
func (msg *VerifyDataReader) SessionKey() *SessionKey {
if msg.details.SessionKey == nil {
return nil
}
alg := getAlgo(msg.details.DecryptedWithAlgorithm)
return NewSessionKeyFromToken(msg.details.SessionKey, alg)
}
// VerifiedDataResult is a result that contains data and
// the result of a potential signature verification on the data.
type VerifiedDataResult struct {
VerifyResult
metadata *LiteralMetadata
data []byte
cachedSessionKey *SessionKey
}
// Metadata returns the associated literal metadata of the data.
func (r *VerifiedDataResult) Metadata() *LiteralMetadata {
return r.metadata
}
// Bytes returns the result data as bytes.
func (r *VerifiedDataResult) Bytes() []byte {
return r.data
}
// String returns the result data as string.
func (r *VerifiedDataResult) String() string {
return string(r.data)
}
// SessionKey returns the session key the data is decrypted with.
// Returns nil, if the data was not encrypted or
// session key caching was not enabled.
func (r *VerifiedDataResult) SessionKey() *SessionKey {
return r.cachedSessionKey
}
// VerifyCleartextResult is a result of a cleartext message verification.
type VerifyCleartextResult struct {
VerifyResult
cleartext []byte
}
// Cleartext returns the parsed plain text of the result.
func (vc *VerifyCleartextResult) Cleartext() []byte {
return vc.cleartext
}