Skip to content

Commit

Permalink
Add password to top level CLI parameters, misc refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mikera committed Jan 18, 2024
1 parent ccebd6a commit 5f28557
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 58 deletions.
32 changes: 18 additions & 14 deletions convex-cli/src/main/java/convex/cli/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import convex.api.Convex;
import convex.cli.client.Query;
import convex.cli.client.Status;
import convex.cli.client.Transaction;
import convex.cli.client.Transact;
import convex.cli.key.Key;
import convex.cli.local.Local;
import convex.cli.output.RecordOutput;
Expand Down Expand Up @@ -48,7 +48,7 @@
Peer.class,
Query.class,
Status.class,
Transaction.class,
Transact.class,
CommandLine.HelpCommand.class
},
usageHelpAutoWidth=true,
Expand All @@ -67,13 +67,25 @@ public class Main implements Runnable {

public CommandLine commandLine=new CommandLine(this);

@Option(names={"-k", "--keystore"},
defaultValue="${env:CONVEX_KEYSTORE_PASSWORD:-" +Constants.KEYSTORE_FILENAME+"}",
@Option(names={"--keystore"},
defaultValue="${env:CONVEX_KEYSTORE:-" +Constants.KEYSTORE_FILENAME+"}",
scope = ScopeType.INHERIT,
description="Keystore filename. Default: ${DEFAULT-VALUE}")
private String keyStoreFilename;

@Option(names={"--k","--key"},
defaultValue="${env:CONVEX_KEY}",
scope = ScopeType.INHERIT,
description="Keystore filename. Default: ${DEFAULT-VALUE}")
private String keySpec;

@Option(names={"--p","--password"},
defaultValue="${env:CONVEX_KEY_PASSWORD}",
scope = ScopeType.INHERIT,
description="Keystore filename. Default: ${DEFAULT-VALUE}")
private String keyPassword;

@Option(names={"--store-password"},
@Option(names={"--keystore-password"},
scope = ScopeType.INHERIT,
defaultValue="${env:CONVEX_KEYSTORE_PASSWORD}",
description="Password to read/write to the Keystore")
Expand Down Expand Up @@ -241,25 +253,17 @@ public char[] getKeyPassword() {
} else {
if (!nonInteractive) {
Console console = System.console();
keypass= console.readPassword("Private Key Password: ");
keypass= console.readPassword("Private Key Encryption Password: ");
}

if (keypass==null) {
log.warn("No password for key: defaulting to blank password");
keypass=new char[0];
}

}
return keypass;
}

/**
* Sets the currently defined keystore password
* @param password Password to use
*/
public void setPassword(String password) {
this.keystorePassword=password;
}

/**
* Gets the keystore file name currently used for the CLI
Expand Down
33 changes: 33 additions & 0 deletions convex-cli/src/main/java/convex/cli/client/AClientCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import convex.api.Convex;
import convex.cli.ATopCommand;
import convex.cli.CLIError;
import convex.cli.Constants;
import convex.core.Result;
import convex.core.crypto.AKeyPair;
import convex.core.data.ABlob;
import convex.core.data.ACell;
import convex.core.data.Address;
import picocli.CommandLine.Option;

Expand Down Expand Up @@ -49,6 +55,33 @@ protected boolean ensureAddress(Convex convex) {
}
return false;
}

protected boolean ensureKeyPair(Convex convex) {
AKeyPair keyPair = convex.getKeyPair();
if (keyPair!=null) return true;

Address address=convex.getAddress();
try {
// Try to identify the required keypair
Result ar=convex.query("*key*").get(1000,TimeUnit.MILLISECONDS);
if (ar.isError()) throw new CLIError("Unable to determine *key* for Address "+address+" : "+ar);

ACell v=ar.getValue();
if (v instanceof ABlob) {
String pk=((ABlob)v).toHexString();
keyPair=mainParent.loadKeyFromStore(pk);
if (keyPair==null) {
// We didn't find required keypair
throw new CLIError("Unable to find keypair with public key "+v+" for Address "+address+" : "+ar);
}
convex.setKeyPair(keyPair);
return true;
}
} catch(Exception e) {
return false;
}
return false;
}

protected convex.api.Convex connect() throws IOException,TimeoutException {
if (port==null) port=convex.core.Constants.DEFAULT_PEER_PORT;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package convex.cli.client;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import convex.api.Convex;
import convex.cli.CLIError;
import convex.core.Result;
import convex.core.crypto.AKeyPair;
import convex.core.data.ABlob;
import convex.core.data.ACell;
import convex.core.data.Address;
import convex.core.lang.Reader;
Expand All @@ -29,13 +25,12 @@
@Command(name="transact",
mixinStandardHelpOptions=true,
description="Execute a user transaction on the Convex network.")
public class Transaction extends AClientCommand {
public class Transact extends AClientCommand {

protected static final Logger log = LoggerFactory.getLogger(Transaction.class);
protected static final Logger log = LoggerFactory.getLogger(Transact.class);

@Option(names={"--public-key"},
defaultValue="",
description="Hex string of the public key in the Keystore to sign the transaction.%n"
description="Hex prefix of the public key in the Keystore to sign the transaction.%n"
+ "You only need to enter in the first distinct hex values of the public key.%n"
+ "For example: 0xf0234 or f0234")
private String keystorePublicKey;
Expand All @@ -49,40 +44,24 @@ public void run() {
try {
Convex convex = connect();
Address address=convex.getAddress();
if (!ensureAddress(convex)) {

if (!ensureAddress(convex)) {
throw new CLIError("Must specify a valid address for transaction.");
}

AKeyPair keyPair = convex.getKeyPair();

// If we don't already have keypair specified, attempt to find
// correct key pair for address from the network
if (keyPair==null) {
Result ar=convex.query("*key*").get(1000,TimeUnit.MILLISECONDS);
if (ar.isError()) throw new CLIError("Unable to get *key* for Address "+address+" : "+ar);
ACell v=ar.getValue();
if (v instanceof ABlob) {
String pk=((ABlob)v).toHexString();
keyPair=mainParent.loadKeyFromStore(pk);
if (keyPair==null) {
// We didn't find required keypair
throw new CLIError("Unable to get keypair "+pk+" for Address "+address+" : "+ar);
}
convex.setKeyPair(keyPair);
}
if (!ensureKeyPair(convex)) {
throw new CLIError("Must provide a key pair to sign transaction.");
}

log.debug("Executing transaction: '{}'\n", transactionCode);
ACell message = Reader.read(transactionCode);
ATransaction transaction = Invoke.create(address, -1, message);
Result result = convex.transactSync(transaction, timeout);
mainParent.printResult(result);
} catch (CLIError e) {
throw e;
} catch (Exception e) {
// General catch all
throw new CLIError("Error executing transation",e);
}
}



}
1 change: 0 additions & 1 deletion convex-cli/src/main/java/convex/cli/key/KeyImport.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public class KeyImport extends AKeyCommand {

@Override
public void run() {
// sub command to generate keys
Main mainParent = cli();
if (importFilename != null && importFilename.length() > 0) {
Path path=Paths.get(importFilename);
Expand Down
2 changes: 1 addition & 1 deletion convex-cli/src/test/java/convex/cli/CLIHelpTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import org.junit.jupiter.api.Test;

import static convex.cli.Helper.assertExecuteCommandLineResult;
import static convex.cli.HelperTest.assertExecuteCommandLineResult;

public class CLIHelpTest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import org.junit.jupiter.api.Test;

public class Helper {
public class HelperTest {

@Test
public void testSplitArray() {
Expand Down
13 changes: 8 additions & 5 deletions convex-cli/src/test/java/convex/cli/key/KeyExportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

public class KeyExportTest {
private static final char[] KEYSTORE_PASSWORD = "testPassword".toCharArray();
private static final char[] KEY_PASSWORD = "testKeytPassword".toCharArray();
private static final char[] EXPORT_PASSWORD = "testExportPassword".toCharArray();

private static final File TEMP_FILE;
Expand All @@ -38,7 +39,8 @@ public void testKeyGenerateAndExport() {
// command key.generate
CLTester tester = CLTester.run(
"key", "generate",
"--store-password", new String(KEYSTORE_PASSWORD),
"--keystore-password", new String(KEYSTORE_PASSWORD),
"--password", new String(KEY_PASSWORD),
"--keystore", KEYSTORE_FILENAME
);
assertEquals(ExitCodes.SUCCESS,tester.getResult());
Expand All @@ -58,9 +60,10 @@ public void testKeyGenerateAndExport() {
tester = CLTester.run(
"key",
"export",
"--store-password", new String(KEYSTORE_PASSWORD),
"--keystore-password", new String(KEYSTORE_PASSWORD),
"--p", new String(KEY_PASSWORD),
"--keystore", KEYSTORE_FILENAME,
"--public-key", publicKey,
"--key", publicKey,
"--export-password", new String(EXPORT_PASSWORD)
);
assertEquals(ExitCodes.SUCCESS,tester.getResult());
Expand All @@ -70,9 +73,9 @@ public void testKeyGenerateAndExport() {
tester = CLTester.run(
"key",
"export",
"--store-password", new String(KEYSTORE_PASSWORD),
"--keystore-password", new String(KEYSTORE_PASSWORD),
"--keystore", KEYSTORE_FILENAME,
"--public-key", "0x" + publicKey,
"--key", "0x" + publicKey,
"--export-password", new String(EXPORT_PASSWORD)
);
assertEquals(ExitCodes.SUCCESS,tester.getResult());
Expand Down
4 changes: 2 additions & 2 deletions convex-cli/src/test/java/convex/cli/key/KeyImportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void testKeyImport() {
"key",
"import",
"-n",
"--store-password", new String(KEYSTORE_PASSWORD),
"--keystore-password", new String(KEYSTORE_PASSWORD),
"--keystore", KEYSTORE_FILENAME,
"--import-text", pemText,
"--import-password", new String(IMPORT_PASSWORD)
Expand All @@ -50,7 +50,7 @@ public void testKeyImport() {
CLTester t2=CLTester.run(
"key" ,
"list",
"--store-password", new String(KEYSTORE_PASSWORD),
"--keystore-password", new String(KEYSTORE_PASSWORD),
"--keystore", KEYSTORE_FILENAME);

assertEquals(ExitCodes.SUCCESS,t2.getResult());
Expand Down
10 changes: 6 additions & 4 deletions convex-cli/src/test/java/convex/cli/key/KeyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class KeyTest {
TEMP_FILE.deleteOnExit();
}
private static final String KEYSTORE_PASSWORD = "testPassword";
private static final String KEY_PASSWORD = "testKeyPassword";

@Test
public void testKeyGenerateAndUse() throws IOException {
Expand All @@ -34,20 +35,21 @@ public void testKeyGenerateAndUse() throws IOException {
String fileName =KEYSTORE_FILENAME;

// command key.generate
CLTester tester = CLTester.run("key", "generate", "--store-password", KEYSTORE_PASSWORD, "--keystore", fileName);
CLTester tester = CLTester.run("key", "generate", "--p", KEY_PASSWORD, "--keystore-password", KEYSTORE_PASSWORD, "--keystore", fileName);
assertEquals(0,tester.getResult());
String key = tester.getOutput().trim();
assertEquals(64,key.length());


File fp = new File(fileName);
assertTrue(fp.exists());

// command key.list
tester = CLTester.run("key", "list", "--store-password", KEYSTORE_PASSWORD, "--keystore", fileName);
tester = CLTester.run("key", "list", "--keystore-password", KEYSTORE_PASSWORD, "--keystore", fileName);
//tester.assertOutputMatch("^Index Public Key\\s+1");

// command key.list with non-existnt keystore
tester = CLTester.run("key", "list", "--store-password", KEYSTORE_PASSWORD, "--keystore","bad-keystore.pfx");
// command key.list with non-existant keystore
tester = CLTester.run("key", "list", "--keystore-password", KEYSTORE_PASSWORD, "--keystore","bad-keystore.pfx");
assertNotEquals(ExitCodes.SUCCESS,tester.getResult());

}
Expand Down

0 comments on commit 5f28557

Please sign in to comment.