diff --git a/.travis.yml b/.travis.yml
index 985d225..f1b65c7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,8 @@
 sudo: false
 language: go
-
+arch:
+  - amd64
+  - ppc64le
 go:
   - 1.8
   - 1.9
diff --git a/Gopkg.lock b/Gopkg.lock
deleted file mode 100644
index d8c94aa..0000000
--- a/Gopkg.lock
+++ /dev/null
@@ -1,19 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
-  branch = "master"
-  name = "rsc.io/qr"
-  packages = [
-    ".",
-    "coding",
-    "gf256"
-  ]
-  revision = "48b2ede4844e13f1a2b7ce4d2529c9af7e359fc5"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  inputs-digest = "b705d306da5a78e76b7ff289744770eef56328a4f0d1c615c1a233d056283651"
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
deleted file mode 100644
index e2fd13b..0000000
--- a/Gopkg.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Gopkg.toml example
-#
-# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
-# for detailed Gopkg.toml documentation.
-#
-# required = ["github.com/user/thing/cmd/thing"]
-# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
-#
-# [[constraint]]
-#   name = "github.com/user/project"
-#   version = "1.0.0"
-#
-# [[constraint]]
-#   name = "github.com/user/project2"
-#   branch = "dev"
-#   source = "github.com/myfork/project2"
-#
-# [[override]]
-#   name = "github.com/x/y"
-#   version = "2.4.0"
-#
-# [prune]
-#   non-go = false
-#   go-tests = true
-#   unused-packages = true
-
-
-[[constraint]]
-  branch = "master"
-  name = "rsc.io/qr"
-
-[prune]
-  go-tests = true
-  unused-packages = true
diff --git a/debian/changelog b/debian/changelog
index f327788..6ebeda3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-gokyle-twofactor (1.1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Tue, 26 Apr 2022 14:44:45 -0000
+
 golang-github-gokyle-twofactor (1.0.1-1) unstable; urgency=medium
 
   [ Michael Stapelberg ]
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..e8d6c5d
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,8 @@
+module github.com/gokyle/twofactor
+
+go 1.14
+
+require (
+	github.com/benbjohnson/clock v0.0.0-20161215174838-7dc76406b6d3
+	rsc.io/qr v0.1.0
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..b54497a
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,4 @@
+github.com/benbjohnson/clock v0.0.0-20161215174838-7dc76406b6d3 h1:wOysYcIdqv3WnvwqFFzrYCFALPED7qkUGaLXu359GSc=
+github.com/benbjohnson/clock v0.0.0-20161215174838-7dc76406b6d3/go.mod h1:UMqtWQTnOe4byzwe7Zhwh8f8s+36uszN51sJrSIZlTE=
+rsc.io/qr v0.1.0 h1:M/sAxsU2J5mlQ4W84Bxga2EgdQqOaAliipcjPmMUM5Q=
+rsc.io/qr v0.1.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
diff --git a/totp.go b/totp.go
index 789de4a..9259e6c 100644
--- a/totp.go
+++ b/totp.go
@@ -11,9 +11,12 @@ import (
 	"net/url"
 	"strconv"
 	"strings"
-	"time"
+
+	"github.com/benbjohnson/clock"
 )
 
+var timeSource = clock.New()
+
 // TOTP represents an RFC 6238 Time-based One-Time Password instance.
 type TOTP struct {
 	*OATH
@@ -50,10 +53,10 @@ func (otp *TOTP) otpCounter(t uint64) uint64 {
 
 // OTPCounter returns the current time value for the OTP.
 func (otp *TOTP) OTPCounter() uint64 {
-	return otp.otpCounter(uint64(time.Now().Unix()))
+	return otp.otpCounter(uint64(timeSource.Now().Unix()))
 }
 
-// NewOTP takes a new key, a starting time, a step, the number of
+// NewTOTP takes a new key, a starting time, a step, the number of
 // digits of output (typically 6 or 8) and the hash algorithm to
 // use, and builds a new OTP.
 func NewTOTP(key []byte, start uint64, step uint64, digits int, algo crypto.Hash) *TOTP {
@@ -163,3 +166,7 @@ func totpFromURL(u *url.URL) (*TOTP, string, error) {
 func (otp *TOTP) QR(label string) ([]byte, error) {
 	return otp.OATH.QR(otp.Type(), label)
 }
+
+func SetClock(c clock.Clock) {
+	timeSource = c
+}
diff --git a/totp_test.go b/totp_test.go
index 244e43e..dc1e438 100644
--- a/totp_test.go
+++ b/totp_test.go
@@ -4,6 +4,9 @@ import (
 	"crypto"
 	"fmt"
 	"testing"
+	"time"
+
+	"github.com/benbjohnson/clock"
 )
 
 var rfcTotpKey = []byte("12345678901234567890")
@@ -53,3 +56,28 @@ func TestTotpRFC(t *testing.T) {
 		}
 	}
 }
+
+func TestTOTPTime(t *testing.T) {
+	otp := GenerateGoogleTOTP()
+
+	testClock := clock.NewMock()
+	testClock.Add(2*time.Minute)
+	SetClock(testClock)
+
+	code := otp.OTP()
+
+	testClock.Add(-1 * time.Minute)
+	if newCode := otp.OTP(); newCode == code {
+		t.Errorf("twofactor: TOTP: previous code %s shouldn't match code %s", newCode, code)
+	}
+
+	testClock.Add(2 * time.Minute)
+	if newCode := otp.OTP(); newCode == code {
+		t.Errorf("twofactor: TOTP: future code %s shouldn't match code %s", newCode, code)
+	}
+
+	testClock.Add(-1 * time.Minute)
+	if newCode := otp.OTP(); newCode != code {
+		t.Errorf("twofactor: TOTP: current code %s shouldn't match code %s", newCode, code)
+	}
+}