Skip to content

Commit ca14aa2

Browse files
committed
Cleanup fixed time and allow using time offset for crypto operations
1 parent d37f4eb commit ca14aa2

File tree

11 files changed

+92
-82
lines changed

11 files changed

+92
-82
lines changed

crypto/attachment_manual_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import (
99
)
1010

1111
func TestManualAttachmentProcessor(t *testing.T) {
12-
pgp.latestServerTime = 1615394034
13-
defer func() { pgp.latestServerTime = testTime }()
12+
defer SetFixedTime(testTime)
13+
SetFixedTime(1615394034)
14+
1415
passphrase := []byte("wUMuF/lkDPYWH/0ZqqY8kJKw7YJg6kS")
1516
pk, err := NewKeyFromArmored(readTestFile("att_key", false))
1617
if err != nil {
@@ -86,8 +87,8 @@ func TestManualAttachmentProcessor(t *testing.T) {
8687
}
8788

8889
func TestManualAttachmentProcessorNotEnoughBuffer(t *testing.T) {
89-
pgp.latestServerTime = 1615394034
90-
defer func() { pgp.latestServerTime = testTime }()
90+
defer SetFixedTime(testTime)
91+
SetFixedTime(1615394034)
9192
passphrase := []byte("wUMuF/lkDPYWH/0ZqqY8kJKw7YJg6kS")
9293
pk, err := NewKeyFromArmored(readTestFile("att_key", false))
9394
if err != nil {
@@ -141,8 +142,9 @@ func TestManualAttachmentProcessorNotEnoughBuffer(t *testing.T) {
141142
}
142143

143144
func TestManualAttachmentProcessorEmptyBuffer(t *testing.T) {
144-
pgp.latestServerTime = 1615394034
145-
defer func() { pgp.latestServerTime = testTime }()
145+
defer SetFixedTime(testTime)
146+
SetFixedTime(1615394034)
147+
146148
passphrase := []byte("wUMuF/lkDPYWH/0ZqqY8kJKw7YJg6kS")
147149
pk, err := NewKeyFromArmored(readTestFile("att_key", false))
148150
if err != nil {

crypto/base_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func readTestFile(name string, trimNewlines bool) string {
2727
}
2828

2929
func init() {
30-
UpdateTime(testTime) // 2019-05-13T13:37:07+00:00
30+
SetFixedTime(testTime) // 2019-05-13T13:37:07+00:00
3131

3232
initGenerateKeys()
3333
initArmoredKeys()

crypto/gopenpgp.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import "sync"
66
// GopenPGP is used as a "namespace" for many of the functions in this package.
77
// It is a struct that keeps track of time skew between server and client.
88
type GopenPGP struct {
9-
latestServerTime int64
10-
generationOffset int64
11-
lock *sync.RWMutex
9+
fixedTime int64
10+
timeOffset int64
11+
lock *sync.RWMutex
1212
}
1313

1414
var pgp = GopenPGP{
15-
latestServerTime: 0,
16-
generationOffset: 0,
17-
lock: &sync.RWMutex{},
15+
fixedTime: 0,
16+
timeOffset: 0,
17+
lock: &sync.RWMutex{},
1818
}
1919

2020
// clone returns a clone of the byte slice. Internal function used to make sure

crypto/key.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ func generateKey(
447447
cfg := &packet.Config{
448448
Algorithm: packet.PubKeyAlgoRSA,
449449
RSABits: bits,
450-
Time: getKeyGenerationTimeGenerator(),
450+
Time: getTimeGenerator(),
451451
DefaultHash: crypto.SHA256,
452452
DefaultCipher: packet.CipherAES256,
453453
DefaultCompressionAlgo: packet.CompressionZLIB,

crypto/key_test.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,25 @@ func TestIsExpired(t *testing.T) {
221221
assert.Exactly(t, true, futureKey.IsExpired())
222222
}
223223

224+
func TestGeneratedWithOffset(t *testing.T) {
225+
defer SetFixedTime(testTime)
226+
SetFixedTime(0)
227+
defer SetTimeOffset(0)
228+
SetTimeOffset(30)
229+
230+
// generate key with offset
231+
keyTestRSA, err := GenerateKey(keyTestName, keyTestDomain, "rsa", 1024)
232+
if err != nil {
233+
panic("Cannot generate RSA key:" + err.Error())
234+
}
235+
236+
// Bring back offset to zero
237+
SetTimeOffset(0)
238+
239+
// Verify if key was generated with offset
240+
assert.GreaterOrEqual(t, keyTestRSA.entity.PrimaryKey.CreationTime.Unix(), GetUnixTime()+30)
241+
}
242+
224243
func TestGenerateKeyWithPrimes(t *testing.T) {
225244
prime1, _ := base64.StdEncoding.DecodeString(
226245
"/thF8zjjk6fFx/y9NId35NFx8JTA7jvHEl+gI0dp9dIl9trmeZb+ESZ8f7bNXUmTI8j271kyenlrVJiqwqk80Q==")
@@ -418,10 +437,8 @@ func TestKeyCapabilities(t *testing.T) {
418437
}
419438

420439
func TestRevokedKeyCapabilities(t *testing.T) {
421-
pgp.latestServerTime = 1632219895
422-
defer func() {
423-
pgp.latestServerTime = testTime
424-
}()
440+
defer SetFixedTime(testTime)
441+
SetFixedTime(1632219895)
425442

426443
revokedKey, err := NewKeyFromArmored(readTestFile("key_revoked", false))
427444
if err != nil {

crypto/keyring_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,10 @@ func TestKeyringCapabilities(t *testing.T) {
236236
}
237237

238238
func TestVerificationTime(t *testing.T) {
239+
defer SetFixedTime(testTime)
240+
SetFixedTime(1632312383)
239241
message := NewPlainMessageFromString("Hello")
240-
pgp.latestServerTime = 1632312383
241-
defer func() {
242-
pgp.latestServerTime = testTime
243-
}()
242+
244243
enc, err := keyRingTestPublic.Encrypt(
245244
message,
246245
keyRingTestPrivate,

crypto/message_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,8 @@ func TestBinaryMessageEncryption(t *testing.T) {
211211
}
212212

213213
func TestIssue11(t *testing.T) {
214-
pgp.latestServerTime = 1559655272
215-
defer func() {
216-
pgp.latestServerTime = testTime
217-
}()
214+
defer SetFixedTime(testTime)
215+
SetFixedTime(1559655272)
218216

219217
var issue11Password = []byte("1234")
220218

@@ -258,8 +256,8 @@ func TestIssue11(t *testing.T) {
258256
}
259257

260258
func TestDummy(t *testing.T) {
261-
pgp.latestServerTime = 1636644417
262-
defer func() { pgp.latestServerTime = testTime }()
259+
defer SetFixedTime(testTime)
260+
SetFixedTime(1636644417)
263261

264262
dummyKey, err := NewKeyFromArmored(readTestFile("key_dummy", false))
265263
if err != nil {

crypto/signature_test.go

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,11 @@ func TestVerifyBinDetachedSig(t *testing.T) {
139139
}
140140

141141
func Test_KeyRing_GetVerifiedSignatureTimestampSuccess(t *testing.T) {
142-
message := NewPlainMessageFromString(testMessage)
142+
defer SetFixedTime(testTime)
143143
var time int64 = 1600000000
144-
pgp.latestServerTime = time
145-
defer func() {
146-
pgp.latestServerTime = testTime
147-
}()
144+
SetFixedTime(time)
145+
message := NewPlainMessageFromString(testMessage)
146+
148147
signature, err := keyRingTestPrivate.SignDetached(message)
149148
if err != nil {
150149
t.Errorf("Got an error while generating the signature: %v", err)
@@ -159,12 +158,10 @@ func Test_KeyRing_GetVerifiedSignatureTimestampSuccess(t *testing.T) {
159158
}
160159

161160
func Test_KeyRing_GetVerifiedSignatureTimestampWithContext(t *testing.T) {
162-
message := NewPlainMessageFromString(testMessage)
161+
defer SetFixedTime(testTime)
163162
var time int64 = 1600000000
164-
pgp.latestServerTime = time
165-
defer func() {
166-
pgp.latestServerTime = testTime
167-
}()
163+
SetFixedTime(time)
164+
message := NewPlainMessageFromString(testMessage)
168165
var testContext = "test-context"
169166
signature, err := keyRingTestPrivate.SignDetachedWithContext(message, NewSigningContext(testContext, true))
170167
if err != nil {
@@ -259,12 +256,10 @@ func getTimestampOfIssuer(signature *PGPSignature, keyID uint64) int64 {
259256
}
260257

261258
func Test_KeyRing_GetVerifiedSignatureTimestampError(t *testing.T) {
262-
message := NewPlainMessageFromString(testMessage)
259+
defer SetFixedTime(testTime)
263260
var time int64 = 1600000000
264-
pgp.latestServerTime = time
265-
defer func() {
266-
pgp.latestServerTime = testTime
267-
}()
261+
SetFixedTime(time)
262+
message := NewPlainMessageFromString(testMessage)
268263
signature, err := keyRingTestPrivate.SignDetached(message)
269264
if err != nil {
270265
t.Errorf("Got an error while generating the signature: %v", err)
@@ -616,12 +611,13 @@ func Test_VerifyDetachedWithDoubleContext(t *testing.T) {
616611
}
617612

618613
func Test_verifySignaturExpire(t *testing.T) {
619-
defer func(t int64) { pgp.latestServerTime = t }(pgp.latestServerTime)
620-
pgp.latestServerTime = 0
614+
defer SetFixedTime(testTime)
615+
SetFixedTime(0)
621616

622617
const lifetime = uint32(time.Hour / time.Second)
623618

624619
cfg := &packet.Config{
620+
Time: GetTime,
625621
Algorithm: packet.PubKeyAlgoEdDSA,
626622
DefaultHash: crypto.SHA256,
627623
DefaultCipher: packet.CipherAES256,
@@ -655,10 +651,7 @@ func Test_verifySignaturExpire(t *testing.T) {
655651

656652
sig := NewPGPSignature(signature.GetBinary())
657653

658-
// packet.PublicKey.KeyExpired will return false here because PublicKey CreationTime has
659-
// nanosecond precision, while pgpcrypto.GetUnixTime() has only second precision.
660-
// Adjust the check time to be in the future to ensure that the key is not expired.
661-
err = keyRing.VerifyDetached(message, sig, GetUnixTime()+1)
654+
err = keyRing.VerifyDetached(message, sig, GetUnixTime())
662655
if err != nil {
663656
t.Fatal(err)
664657
}

crypto/time.go

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ import (
44
"time"
55
)
66

7-
// UpdateTime updates cached time.
8-
func UpdateTime(newTime int64) {
7+
// SetFixedTime updates fixed time used for crypto operations.
8+
// Setting 0 will cause system time to be used.
9+
func SetFixedTime(newTime int64) {
910
pgp.lock.Lock()
1011
defer pgp.lock.Unlock()
1112

12-
if newTime > pgp.latestServerTime {
13-
pgp.latestServerTime = newTime
14-
}
13+
pgp.fixedTime = newTime
1514
}
1615

17-
// SetKeyGenerationOffset updates the offset when generating keys.
18-
func SetKeyGenerationOffset(offset int64) {
16+
// SetTimeOffset updates time offset used for crypto operations.
17+
// Offset will be applied to all crypto operations unless fixed time is used.
18+
func SetTimeOffset(newOffset int64) {
1919
pgp.lock.Lock()
2020
defer pgp.lock.Unlock()
2121

22-
pgp.generationOffset = offset
22+
pgp.timeOffset = newOffset
2323
}
2424

2525
// GetUnixTime gets latest cached time.
@@ -39,31 +39,14 @@ func getNow() time.Time {
3939
pgp.lock.RLock()
4040
defer pgp.lock.RUnlock()
4141

42-
if pgp.latestServerTime == 0 {
43-
return time.Now()
42+
if pgp.fixedTime == 0 {
43+
return time.Unix(time.Now().Unix()+pgp.timeOffset, 0)
4444
}
4545

46-
return time.Unix(pgp.latestServerTime, 0)
46+
return time.Unix(pgp.fixedTime, 0)
4747
}
4848

4949
// getTimeGenerator Returns a time generator function.
5050
func getTimeGenerator() func() time.Time {
5151
return getNow
5252
}
53-
54-
// getNowKeyGenerationOffset returns the current time with the key generation offset.
55-
func getNowKeyGenerationOffset() time.Time {
56-
pgp.lock.RLock()
57-
defer pgp.lock.RUnlock()
58-
59-
if pgp.latestServerTime == 0 {
60-
return time.Unix(time.Now().Unix()+pgp.generationOffset, 0)
61-
}
62-
63-
return time.Unix(pgp.latestServerTime+pgp.generationOffset, 0)
64-
}
65-
66-
// getKeyGenerationTimeGenerator Returns a time generator function with the key generation offset.
67-
func getKeyGenerationTimeGenerator() func() time.Time {
68-
return getNowKeyGenerationOffset
69-
}

crypto/time_test.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,29 @@ import (
77
"github.com/stretchr/testify/assert"
88
)
99

10-
func TestTime(t *testing.T) {
11-
UpdateTime(1571072494)
10+
func Test_SetFixedTime(t *testing.T) {
11+
defer SetFixedTime(testTime)
12+
SetFixedTime(1571072494)
1213
time.Sleep(1 * time.Second)
1314
now := GetUnixTime()
1415

15-
assert.Exactly(t, int64(1571072494), now) // Use latest server time
16-
UpdateTime(testTime)
16+
assert.Exactly(t, int64(1571072494), now) // Use fixed time
17+
}
18+
19+
func Test_TimeOffset(t *testing.T) {
20+
defer SetFixedTime(testTime)
21+
defer SetTimeOffset(0)
22+
SetFixedTime(testTime)
23+
SetTimeOffset(30)
24+
time.Sleep(1 * time.Second)
25+
now := GetUnixTime()
26+
27+
assert.Exactly(t, int64(testTime), now) // Use fixed time without offset
28+
29+
SetFixedTime(0)
30+
SetTimeOffset(0)
31+
now = GetUnixTime()
32+
SetTimeOffset(30)
33+
34+
assert.GreaterOrEqual(t, GetUnixTime(), now+30) // Use offset with no fixed time
1735
}

0 commit comments

Comments
 (0)