Fix: use verifyTime in the config time instead of Now()

When decrypting message, we have to use verifyTime in the config
otherwise signatures not valid at verifyTime but valid at Now()
will be seen as valid.
This commit is contained in:
marin thiercelin 2021-09-23 10:40:56 +02:00
parent 0b639a2d93
commit 5558d4a177
No known key found for this signature in database
GPG key ID: 117C025B1F21B2C6
4 changed files with 68 additions and 2 deletions

View file

@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Use the provided `verifyTime` instead of the current time when verifying embedded signatures.
## [2.2.3] 2021-09-21 ## [2.2.3] 2021-09-21
### Changed ### Changed
- Keys are now generated with ZLIB as preferred compression algorithm - Keys are now generated with ZLIB as preferred compression algorithm

View file

@ -5,6 +5,7 @@ import (
"crypto" "crypto"
"io" "io"
"io/ioutil" "io/ioutil"
"time"
"github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/ProtonMail/go-crypto/openpgp/packet"
@ -190,6 +191,7 @@ func asymmetricDecrypt(
encryptedIO, encryptedIO,
privateKey, privateKey,
verifyKey, verifyKey,
verifyTime,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -215,7 +217,10 @@ func asymmetricDecrypt(
// Core for decryption+verification (all) functions. // Core for decryption+verification (all) functions.
func asymmetricDecryptStream( func asymmetricDecryptStream(
encryptedIO io.Reader, privateKey *KeyRing, verifyKey *KeyRing, encryptedIO io.Reader,
privateKey *KeyRing,
verifyKey *KeyRing,
verifyTime int64,
) (messageDetails *openpgp.MessageDetails, err error) { ) (messageDetails *openpgp.MessageDetails, err error) {
privKeyEntries := privateKey.entities privKeyEntries := privateKey.entities
var additionalEntries openpgp.EntityList var additionalEntries openpgp.EntityList
@ -228,7 +233,19 @@ func asymmetricDecryptStream(
privKeyEntries = append(privKeyEntries, additionalEntries...) privKeyEntries = append(privKeyEntries, additionalEntries...)
} }
config := &packet.Config{Time: getTimeGenerator()} config := &packet.Config{
Time: func() time.Time {
if verifyTime == 0 {
/*
We default to current time while decrypting and verifying
but the caller will remove signature expiration errors later on.
See processSignatureExpiration().
*/
return getNow()
}
return time.Unix(verifyTime, 0)
},
}
messageDetails, err = openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config) messageDetails, err = openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config)
if err != nil { if err != nil {

View file

@ -194,6 +194,7 @@ func (keyRing *KeyRing) DecryptStream(
message, message,
keyRing, keyRing,
verifyKeyRing, verifyKeyRing,
verifyTime,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -3,11 +3,13 @@ package crypto
import ( import (
"crypto/ed25519" "crypto/ed25519"
"crypto/rsa" "crypto/rsa"
"errors"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/ProtonMail/go-crypto/openpgp/ecdh" "github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/gopenpgp/v2/constants"
) )
var testSymmetricKey []byte var testSymmetricKey []byte
@ -231,3 +233,43 @@ func TestKeyringCapabilities(t *testing.T) {
assert.True(t, keyRingTestMultiple.CanVerify()) assert.True(t, keyRingTestMultiple.CanVerify())
assert.True(t, keyRingTestMultiple.CanEncrypt()) assert.True(t, keyRingTestMultiple.CanEncrypt())
} }
func TestVerificationTime(t *testing.T) {
message := NewPlainMessageFromString("Hello")
pgp.latestServerTime = 1632312383
defer func() {
pgp.latestServerTime = testTime
}()
enc, err := keyRingTestPublic.Encrypt(
message,
keyRingTestPrivate,
)
if err != nil {
t.Fatalf("Encryption error: %v", err)
}
_, err = keyRingTestPrivate.Decrypt(
enc,
keyRingTestPublic,
392039755,
)
if err == nil {
t.Fatal("No signature error")
}
castedErr := &SignatureVerificationError{}
isType := errors.As(err, castedErr)
if !isType {
t.Fatalf("No signature error %v", err)
}
if castedErr.Status != constants.SIGNATURE_FAILED {
t.Fatalf("Wrong status %v", castedErr)
}
_, err = keyRingTestPrivate.Decrypt(
enc,
keyRingTestPublic,
0,
)
if err != nil {
t.Fatalf("Got an error while decrypting %v", err)
}
}