burrow/src/main/java/io/rudefox/burrow/MnemonicCommand.java

125 lines
4.0 KiB
Java
Raw Normal View History

package io.rudefox.burrow;
import com.bjdweck.bitcoin.mnemonic.Entropy;
import picocli.CommandLine;
import java.security.SecureRandom;
import java.util.Scanner;
@CommandLine.Command(name = "mnemonic", description = "generate mnemonic sentence")
public class MnemonicCommand implements Runnable {
private static final int DEFAULT_BITS_OF_ENTROPY = 256;
private boolean isDiceEntropy() {
return entropyOptions != null && (entropyOptions.isDice6Entropy || entropyOptions.isDice8Entropy);
}
private boolean isInteractiveMode() {
return entropyOptions != null && entropyOptions.eventMethod.isInteractiveMode;
}
private boolean isDice6InteractiveMode() {
return isInteractiveMode() && entropyOptions.isDice6Entropy;
}
private boolean isDice8InteractiveMode() {
return isInteractiveMode() && entropyOptions.isDice8Entropy;
}
@CommandLine.ArgGroup(exclusive = false)
EntropyOptions entropyOptions;
static class EntropyOptions {
@CommandLine.Option(names = {"-6", "--dice6-entropy"},
description = "use 6-sided dice entropy source")
boolean isDice6Entropy;
@CommandLine.Option(names = {"-8", "--dice8-entropy"},
description = "use 8-sided dice entropy source")
boolean isDice8Entropy;
@CommandLine.ArgGroup(multiplicity = "1")
EventMethod eventMethod;
static class EventMethod {
@CommandLine.Option(names = {"-e", "--events"}, paramLabel = "[1-6]{100}|[1-8]{86}",
description = "string representing events from entropy source",
required = true)
String getEventString;
@CommandLine.Option(names = {"-i", "--interactive"},
description = "use interactive command line mode",
required = true)
boolean isInteractiveMode;
}
}
@CommandLine.Option(names = {"-b", "--bits"}, defaultValue = DEFAULT_BITS_OF_ENTROPY+"",
description = "bits of entropy (default: 256)",
paramLabel = "128|160|192|224|256")
int targetBitsOfEntropy;
public void run() {
Entropy entropyBytes = getEntropy();
System.out.println(entropyBytes.toMnemonic().getSentence());
}
Entropy getEntropy() {
if (!isDiceEntropy())
return getGeneratedEntropy();
DiceEventBuffer diceEventBuffer;
if (entropyOptions.isDice6Entropy)
diceEventBuffer = new DiceEventBuffer(this.targetBitsOfEntropy, 6);
else
diceEventBuffer = new DiceEventBuffer(this.targetBitsOfEntropy, 8);
if (isDice6InteractiveMode())
return getDice6EntropyInteractive(diceEventBuffer);
if (isDice8InteractiveMode())
return new Dice8EntropyGenerator(targetBitsOfEntropy, new Scanner(System.in), CommandLine.Help.Ansi.AUTO.enabled()).generate();
diceEventBuffer.appendEvents(entropyOptions.eventMethod.getEventString);
return diceEventBuffer.toEntropy();
}
private Entropy getDice6EntropyInteractive(DiceEventBuffer diceEventBuffer) {
int requiredEvents = diceEventBuffer.getRequiredEvents();
Scanner scanner = new Scanner(System.in);
boolean firstIteration = true;
while (diceEventBuffer.events() < requiredEvents) {
int remainingEvents = requiredEvents - diceEventBuffer.events();
System.out.print(String.format("Input %d %sdice rolls [1-6]: ", remainingEvents, (firstIteration ? "" : "more ")));
String inputString = scanner.next();
diceEventBuffer.appendEvents(inputString);
firstIteration = false;
}
return diceEventBuffer.toEntropy();
}
private Entropy getGeneratedEntropy() {
SecureRandom random = new SecureRandom();
int byteLength = targetBitsOfEntropy / 8;
byte[] randomBytes = new byte[byteLength];
random.nextBytes(randomBytes);
return Entropy.fromRawEntropy(randomBytes);
}
2020-09-01 12:18:32 +00:00
}