From 375ede29d5aba31105ab8b7cc046caeeaacc9205 Mon Sep 17 00:00:00 2001 From: mikera Date: Tue, 30 Jan 2024 12:27:57 +0000 Subject: [PATCH] Strict security "paranoid" CLI mode, extra tests --- convex-cli/src/main/java/convex/cli/Main.java | 21 +++++++++++++++---- .../main/java/convex/cli/key/KeyExport.java | 1 + .../src/test/java/convex/cli/CLTester.java | 9 ++++++++ .../src/test/java/convex/cli/key/KeyTest.java | 9 ++++++-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/convex-cli/src/main/java/convex/cli/Main.java b/convex-cli/src/main/java/convex/cli/Main.java index d1ac4c605..8b61ad41e 100644 --- a/convex-cli/src/main/java/convex/cli/Main.java +++ b/convex-cli/src/main/java/convex/cli/Main.java @@ -77,17 +77,23 @@ public class Main implements Runnable { description="Keystore filename. Default: ${DEFAULT-VALUE}") private String keyStoreFilename; - @Option(names={"--k","--key"}, + @Option(names={"-k","--key"}, defaultValue="${env:CONVEX_KEY}", scope = ScopeType.INHERIT, description="Keystore filename. Default: ${DEFAULT-VALUE}") private String keySpec; - @Option(names={"--p","--password"}, + @Option(names={"-p","--password"}, defaultValue="${env:CONVEX_KEY_PASSWORD}", scope = ScopeType.INHERIT, description="Keystore filename. Default: ${DEFAULT-VALUE}") private String keyPassword; + + @Option(names={"-S","--strict-security"}, + defaultValue="false", + scope = ScopeType.INHERIT, + description="Apply strict security. Will forbid actions with dubious security implications.") + private boolean paranoid; @Option(names={"--keystore-password"}, scope = ScopeType.INHERIT, @@ -237,6 +243,7 @@ public char[] getStorePassword() { } if (storepass==null) { + paranoia("Keystore password must be explicitly provided"); log.warn("No password for keystore: defaulting to blank password"); storepass=new char[0]; } @@ -350,7 +357,7 @@ public AKeyPair loadKeyFromStore(String publicKey) { File keyFile = new File(getKeyStoreFilename()); try { if (!keyFile.exists()) { - throw new Error("Cannot find keystore file "+keyFile.getCanonicalPath()); + throw new CLIError("Cannot find keystore file "+keyFile.getCanonicalPath()); } KeyStore keyStore = PFXTools.loadStore(keyFile, storePassword); @@ -426,7 +433,9 @@ public void saveKeyStore(char[] storePassword) { } } - + public boolean isParanoid() { + return this.paranoid; + } public void println(String s) { if (s==null) s="null"; @@ -484,5 +493,9 @@ public void printErr(String message) { commandLine.getErr().println(message); } + public void paranoia(String message) { + if (isParanoid()) throw new CLIError("STRICT SECURITY: "+message); + } + } diff --git a/convex-cli/src/main/java/convex/cli/key/KeyExport.java b/convex-cli/src/main/java/convex/cli/key/KeyExport.java index 244c7abbb..57847ecc1 100644 --- a/convex-cli/src/main/java/convex/cli/key/KeyExport.java +++ b/convex-cli/src/main/java/convex/cli/key/KeyExport.java @@ -74,6 +74,7 @@ public void run() { String pemText = PEMTools.encryptPrivateKeyToPEM(keyPair.getPrivate(), exportPassword.toCharArray()); output=pemText; } else if ("seed".equals(type)){ + cli().paranoia("Raw seed export forbidden in strict mode."); String rawSeed = keyPair.getSeed().toHexString(); output=rawSeed; } else { diff --git a/convex-cli/src/test/java/convex/cli/CLTester.java b/convex-cli/src/test/java/convex/cli/CLTester.java index 3faf190f8..7181e8509 100644 --- a/convex-cli/src/test/java/convex/cli/CLTester.java +++ b/convex-cli/src/test/java/convex/cli/CLTester.java @@ -1,6 +1,8 @@ package convex.cli; +import static org.junit.jupiter.api.Assertions.fail; + import java.io.PrintWriter; import java.io.StringWriter; @@ -53,4 +55,11 @@ public String[] getArgs() { public String getError() { return error; } + + public void assertResult(int expected) { + if (result==expected) return; + System.err.println("STDOUT: "+output); + System.err.println("STDERR: "+error); + fail("Unexpected CLI result, expected "+expected+" but got "+result); + } } diff --git a/convex-cli/src/test/java/convex/cli/key/KeyTest.java b/convex-cli/src/test/java/convex/cli/key/KeyTest.java index beebd3c47..df9a9a31d 100644 --- a/convex-cli/src/test/java/convex/cli/key/KeyTest.java +++ b/convex-cli/src/test/java/convex/cli/key/KeyTest.java @@ -35,8 +35,13 @@ public void testKeyGenerateAndUse() throws IOException { String fileName =KEYSTORE_FILENAME; // command key.generate - CLTester tester = CLTester.run("key", "generate", "--p", KEY_PASSWORD, "--keystore-password", KEYSTORE_PASSWORD, "--keystore", fileName); - assertEquals(0,tester.getResult()); + CLTester tester = CLTester.run( + "key", + "generate", + "-p", KEY_PASSWORD, + "--keystore-password", KEYSTORE_PASSWORD, + "--keystore", fileName); + tester.assertResult(0); String key = tester.getOutput().trim(); assertEquals(64,key.length());