From 05f5266495e21956172486e5666d9361861ecff8 Mon Sep 17 00:00:00 2001 From: Dmitriy Matrenichev Date: Fri, 12 May 2023 19:42:52 -0400 Subject: [PATCH] packet.Config.Time should return time with 999999999 nsec Currently verifySignature accepts seconds for verification, but internally it uses time.Time for comparison. That means if we created openpgp.Entity with default time field, test can fail with "key expired" error because PublicKey.KeyExpired will think that key creation happened before verifyTime when in reality we just lost the nsec precision. Signed-off-by: Dmitriy Matrenichev --- crypto/signature.go | 4 ++-- crypto/signature_test.go | 31 +++++++++++++++++++++++++++++++ crypto/time.go | 2 +- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/crypto/signature.go b/crypto/signature.go index f5c58ab3..921eabe2 100644 --- a/crypto/signature.go +++ b/crypto/signature.go @@ -240,7 +240,7 @@ func verifySignature( } } else { config.Time = func() time.Time { - return time.Unix(verifyTime+internal.CreationTimeOffset, 0) + return time.Unix(verifyTime+internal.CreationTimeOffset, 999999999) } } @@ -258,7 +258,7 @@ func verifySignature( // Maybe the creation time offset pushed it over the edge // Retry with the actual verification time config.Time = func() time.Time { - return time.Unix(verifyTime, 0) + return time.Unix(verifyTime, 999999999) } seeker, ok := origText.(io.ReadSeeker) diff --git a/crypto/signature_test.go b/crypto/signature_test.go index de32e1f9..85a5ec15 100644 --- a/crypto/signature_test.go +++ b/crypto/signature_test.go @@ -13,6 +13,7 @@ import ( "github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/ProtonMail/gopenpgp/v2/constants" ) @@ -663,3 +664,33 @@ func Test_verifySignaturExpire(t *testing.T) { t.Fatal(err) } } + +func TestKeyNotExpired(t *testing.T) { + 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, + Time: func() time.Time { return time.Unix(GetUnixTime(), 42) }, + } + + entity, err := openpgp.NewEntity("John Smith", "Linux", "john.smith@example.com", cfg) + require.NoError(t, err) + key, err := NewKeyFromEntity(entity) + require.NoError(t, err) + keyRing, err := NewKeyRing(key) + require.NoError(t, err) + + data := []byte("Hello, World!") + message := NewPlainMessage(data) + signature, err := keyRing.SignDetached(message) + require.NoError(t, err) + + sig := NewPGPSignature(signature.GetBinary()) + err = keyRing.VerifyDetached(message, sig, GetUnixTime()) + require.NoError(t, err) +} diff --git a/crypto/time.go b/crypto/time.go index b208d874..6bd92d4b 100644 --- a/crypto/time.go +++ b/crypto/time.go @@ -43,7 +43,7 @@ func getNow() time.Time { return time.Now() } - return time.Unix(pgp.latestServerTime, 0) + return time.Unix(pgp.latestServerTime, 999999999) } // getTimeGenerator Returns a time generator function.