2020-09-01 14:09:20 +00:00
|
|
|
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())
|
2020-09-25 09:09:04 +00:00
|
|
|
return new Dice8EntropyGenerator(targetBitsOfEntropy, new Scanner(System.in), CommandLine.Help.Ansi.AUTO.enabled()).generate();
|
2020-09-01 14:09:20 +00:00
|
|
|
|
|
|
|
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
|
|
|
}
|