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 149
|
package crypto
import (
"errors"
"fmt"
"io"
openpgp "github.com/ProtonMail/go-crypto/openpgp/v2"
)
// 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, fmt.Errorf("gopenpgp: discarding data from reader failed: %w", err)
}
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, fmt.Errorf("gopenpgp: reading all data from reader failed: %w", err)
}
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
}
|