diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 50907fed986d0308c21502ce804a4936ee4a683c..3dbc8ccd00e6315eb4c04634d97340f007fa029f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -60,6 +60,8 @@ jobs:
     needs: build
     # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
+      - name: download minisign
+        run: sudo add-apt-repository ppa:dysfunctionalprogramming/minisign && sudo apt-get update && sudo apt-get install minisign
       # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
       - uses: actions/checkout@v2
       - name: Docker Build
diff --git a/tests/e2e_test.go b/tests/e2e_test.go
index eebeaf604fa01be62ce68f5ad2ecbb2ccac412a2..a77befc4edd5b2083c9538bbe71b90f2b1aad571 100644
--- a/tests/e2e_test.go
+++ b/tests/e2e_test.go
@@ -106,3 +106,33 @@ func TestGet(t *testing.T) {
 	}
 	// TODO: check the actual data in here.
 }
+
+func TestMinisign(t *testing.T) {
+	// Create a keypair
+	keyPath := filepath.Join(t.TempDir(), "minisign.key")
+	pubPath := filepath.Join(t.TempDir(), "minisign.pub")
+
+	// Set an empty password, we have to hit enter twice to confirm
+	run(t, "\n\n", "minisign", "-G", "-s", keyPath, "-p", pubPath)
+
+	// Create a random artifact and sign it.
+	artifactPath := filepath.Join(t.TempDir(), "artifact")
+	sigPath := filepath.Join(t.TempDir(), "signature.asc")
+	createArtifact(t, artifactPath)
+
+	// Send in one empty password over stdin
+	out := run(t, "\n", "minisign", "-S", "-s", keyPath, "-m", artifactPath, "-x", sigPath)
+	t.Log(out)
+
+	// Now upload to the log!
+	out = runCli(t, "upload", "--artifact", artifactPath, "--signature", sigPath,
+		"--public-key", pubPath, "--signature-format", "minisign")
+	outputContains(t, out, "Created entry at")
+
+	// Wait and check it.
+	time.Sleep(3 * time.Second)
+
+	out = runCli(t, "verify", "--artifact", artifactPath, "--signature", sigPath,
+		"--public-key", pubPath, "--signature-format", "minisign")
+	outputContains(t, out, "Inclusion Proof")
+}
diff --git a/tests/pgp.go b/tests/pgp.go
index 9168321443ecb16701a8764489187f1275f82406..19a9b694fb1e685762704f2f6824eb142aa7e3a3 100644
--- a/tests/pgp.go
+++ b/tests/pgp.go
@@ -5,6 +5,7 @@ package e2e
 import (
 	"bytes"
 	"io"
+	"io/ioutil"
 	"strings"
 	"testing"
 
@@ -157,3 +158,15 @@ func Sign(t *testing.T, m io.Reader) []byte {
 	}
 	return b.Bytes()
 }
+
+// createdSignedArtifact gets the test dir setup correctly with some random artifacts and keys.
+func createdSignedArtifact(t *testing.T, artifactPath, sigPath string) {
+	t.Helper()
+	artifact := createArtifact(t, artifactPath)
+
+	// Sign it with our key and write that to a file
+	signature := Sign(t, strings.NewReader(artifact))
+	if err := ioutil.WriteFile(sigPath, []byte(signature), 0644); err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/tests/util.go b/tests/util.go
index 3d1ff59366a51afd60e91322a0a1c1b6e9f22979..8ea6e0f607343a335bfa1c1a08399abb74d94cfe 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -24,10 +24,13 @@ func outputContains(t *testing.T, output, sub string) {
 	}
 }
 
-func runCli(t *testing.T, arg ...string) string {
+func run(t *testing.T, stdin, cmd string, arg ...string) string {
 	t.Helper()
-	cmd := exec.Command(cli, arg...)
-	b, err := cmd.CombinedOutput()
+	c := exec.Command(cmd, arg...)
+	if stdin != "" {
+		c.Stdin = strings.NewReader(stdin)
+	}
+	b, err := c.CombinedOutput()
 	if err != nil {
 		t.Log(string(b))
 		t.Fatal(err)
@@ -35,6 +38,11 @@ func runCli(t *testing.T, arg ...string) string {
 	return string(b)
 }
 
+func runCli(t *testing.T, arg ...string) string {
+	t.Helper()
+	return run(t, "", cli, arg...)
+}
+
 func runCliErr(t *testing.T, arg ...string) {
 	t.Helper()
 	cmd := exec.Command(cli, arg...)
@@ -53,8 +61,7 @@ func readFile(t *testing.T, p string) string {
 	return strings.TrimSpace(string(b))
 }
 
-// createdSignedArtifact gets the test dir setup correctly with some random artifacts and keys.
-func createdSignedArtifact(t *testing.T, artifactPath, sigPath string) {
+func createArtifact(t *testing.T, artifactPath string) string {
 	t.Helper()
 	// First let's generate some random data so we don't have to worry about dupes.
 	rand.Seed(time.Now().UnixNano())
@@ -68,10 +75,5 @@ func createdSignedArtifact(t *testing.T, artifactPath, sigPath string) {
 	if err := ioutil.WriteFile(artifactPath, []byte(artifact), 0644); err != nil {
 		t.Fatal(err)
 	}
-
-	// Sign it with our key and write that to a file
-	signature := Sign(t, strings.NewReader(artifact))
-	if err := ioutil.WriteFile(sigPath, []byte(signature), 0644); err != nil {
-		t.Fatal(err)
-	}
+	return artifact
 }