Merge pull request #233 from DmitriyMV/fix-verify-retry

Reset origText in verifySignature before the retry
This commit is contained in:
marinthiercelin 2023-04-14 10:02:36 +02:00 committed by GitHub
commit 5aebf6a366
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 3 deletions

View file

@ -251,7 +251,7 @@ func verifySignature(
sig, signer, err := openpgp.VerifyDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config) sig, signer, err := openpgp.VerifyDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config)
if sig != nil && signer != nil && (errors.Is(err, pgpErrors.ErrSignatureExpired) || errors.Is(err, pgpErrors.ErrKeyExpired)) { if sig != nil && signer != nil && (errors.Is(err, pgpErrors.ErrSignatureExpired) || errors.Is(err, pgpErrors.ErrKeyExpired)) { //nolint:nestif
if verifyTime == 0 { // Expiration check disabled if verifyTime == 0 { // Expiration check disabled
err = nil err = nil
} else { } else {
@ -261,12 +261,22 @@ func verifySignature(
return time.Unix(verifyTime, 0) return time.Unix(verifyTime, 0)
} }
seeker, ok := origText.(io.ReadSeeker)
if !ok {
return nil, errors.Wrap(err, "gopenpgp: message reader do not support seeking, cannot retry signature verification")
}
_, err = seeker.Seek(0, io.SeekStart)
if err != nil {
return nil, newSignatureFailed(errors.Wrap(err, "gopenpgp: could not rewind the data reader."))
}
_, err = signatureReader.Seek(0, io.SeekStart) _, err = signatureReader.Seek(0, io.SeekStart)
if err != nil { if err != nil {
return nil, newSignatureFailed(err) return nil, newSignatureFailed(err)
} }
sig, signer, err = openpgp.VerifyDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config) sig, signer, err = openpgp.VerifyDetachedSignatureAndHash(pubKeyEntries, seeker, signatureReader, allowedHashes, config)
} }
} }

View file

@ -2,15 +2,19 @@ package crypto
import ( import (
"bytes" "bytes"
"crypto"
"errors" "errors"
"io" "io"
"io/ioutil" "io/ioutil"
"regexp" "regexp"
"testing" "testing"
"time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/ProtonMail/gopenpgp/v2/constants"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/ProtonMail/gopenpgp/v2/constants"
) )
const testMessage = "Hello world!" const testMessage = "Hello world!"
@ -610,3 +614,52 @@ func Test_VerifyDetachedWithDoubleContext(t *testing.T) {
// then // then
checkVerificationError(t, err, constants.SIGNATURE_BAD_CONTEXT) checkVerificationError(t, err, constants.SIGNATURE_BAD_CONTEXT)
} }
func Test_verifySignaturExpire(t *testing.T) {
defer func(t int64) { pgp.latestServerTime = t }(pgp.latestServerTime)
pgp.latestServerTime = 0
const lifetime = uint32(time.Hour / time.Second)
cfg := &packet.Config{
Algorithm: packet.PubKeyAlgoEdDSA,
DefaultHash: crypto.SHA256,
DefaultCipher: packet.CipherAES256,
DefaultCompressionAlgo: packet.CompressionZLIB,
KeyLifetimeSecs: lifetime,
SigLifetimeSecs: lifetime,
}
entity, err := openpgp.NewEntity("John Smith", "Linux", "john.smith@example.com", cfg)
if err != nil {
t.Fatal(err)
}
key, err := NewKeyFromEntity(entity)
if err != nil {
t.Fatal(err)
}
keyRing, err := NewKeyRing(key)
if err != nil {
t.Fatal(err)
}
data := []byte("Hello, World!")
message := NewPlainMessage(data)
signature, err := keyRing.SignDetached(message)
if err != nil {
t.Fatalf("%#+v", err)
}
sig := NewPGPSignature(signature.GetBinary())
// packet.PublicKey.KeyExpired will return false here because PublicKey CreationTime has
// nanosecond precision, while pgpcrypto.GetUnixTime() has only second precision.
// Adjust the check time to be in the future to ensure that the key is not expired.
err = keyRing.VerifyDetached(message, sig, GetUnixTime()+1)
if err != nil {
t.Fatal(err)
}
}