diff --git a/openpgp/packet/config.go b/openpgp/packet/config.go index 04994bec9..11fdfbd20 100644 --- a/openpgp/packet/config.go +++ b/openpgp/packet/config.go @@ -29,6 +29,10 @@ type Config struct { // Time returns the current time as the number of seconds since the // epoch. If Time is nil, time.Now is used. Time func() time.Time + // Ignore Key Expiration, some clients may not care about expiration + IgnoreKeyExpiration bool + // Ignore Signature Expiration, some clients may not care about expiration + IgnoreSignatureExpiration bool // DefaultCompressionAlgo is the compression algorithm to be // applied to the plaintext before encryption. If zero, no // compression is done. diff --git a/openpgp/read.go b/openpgp/read.go index 8499c7379..8f1513e0d 100644 --- a/openpgp/read.go +++ b/openpgp/read.go @@ -548,7 +548,8 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader, // - The signing subkey binding signature is expired // - The signing subkey cross-signature is expired // -// NOTE: The order of these checks is important, as the caller may choose to +// NOTE (deprecated, use config.Ignore(Key/Signature)Expiration): +// The order of these checks is important, as the caller may choose to // ignore ErrSignatureExpired or ErrKeyExpired errors, but should never // ignore any other errors. // @@ -570,22 +571,26 @@ func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet } } } - if key.Entity.Revoked(now) || // primary key is revoked - (signedBySubKey && key.Revoked(now)) || // subkey is revoked - primaryIdentity.Revoked(now) { // primary identity is revoked - return errors.ErrKeyRevoked - } - if key.Entity.PrimaryKey.KeyExpired(primaryIdentity.SelfSignature, now) { // primary key is expired - return errors.ErrKeyExpired - } - if signedBySubKey { - if key.PublicKey.KeyExpired(key.SelfSignature, now) { // subkey is expired + if config == nil || !config.IgnoreKeyExpiration { + if key.Entity.Revoked(now) || // primary key is revoked + (signedBySubKey && key.Revoked(now)) || // subkey is revoked + primaryIdentity.Revoked(now) { // primary identity is revoked + return errors.ErrKeyRevoked + } + if key.Entity.PrimaryKey.KeyExpired(primaryIdentity.SelfSignature, now) { // primary key is expired return errors.ErrKeyExpired } + if signedBySubKey { + if key.PublicKey.KeyExpired(key.SelfSignature, now) { // subkey is expired + return errors.ErrKeyExpired + } + } } - for _, sig := range sigsToCheck { - if sig.SigExpired(now) { // any of the relevant signatures are expired - return errors.ErrSignatureExpired + if config == nil || !config.IgnoreSignatureExpiration { + for _, sig := range sigsToCheck { + if sig.SigExpired(now) { // any of the relevant signatures are expired + return errors.ErrSignatureExpired + } } } return nil diff --git a/openpgp/read_test.go b/openpgp/read_test.go index bffa1c538..4ab4a2f05 100644 --- a/openpgp/read_test.go +++ b/openpgp/read_test.go @@ -433,6 +433,11 @@ func TestDetachedSignatureExpiredCrossSig(t *testing.T) { if err != errors.ErrSignatureExpired { t.Fatalf("Unexpected class of error: %s", err) } + config.IgnoreSignatureExpiration = true + _, err = CheckArmoredDetachedSignature(kring, bytes.NewBufferString("Hello World :)"), bytes.NewBufferString(sigFromKeyWithExpiredCrossSig), config) + if err != nil { + t.Fatalf("Expected signature expiration check to be skipped") + } } func TestSignatureUnknownNotation(t *testing.T) {