9 Commits
6 changed files with 81 additions and 58 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 B.J. Dweck
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+16 -50
View File
@@ -2,64 +2,30 @@
*Offline Bitcoin Seed Generation and Wallet Tool*
Use [Rudefox](https://rudefox.io/) Burrow on an air-gapped, single-board computer, like a Raspberry Pi, to generate new seed words, derive addresses and extended public keys from existing seed words or sign PSBT transactions offline.
Use Burrow on an air-gapped, single-board computer, like a Raspberry Pi, to generate new seed words, derive addresses and extended public keys from existing seed words or sign PSBT transactions offline. Check out the self-audited seed generation feature: [ShowMyWork](https://rudefox.io/blog/2020-07-16-show-my-work.html).
## Unique Feature: ShowMyWork
[Rudefox Burrow](https://rudefox.io/burrow/) is released under the [MIT License](LICENSE.md) by B.J. Dweck
[**Rudefox ShowMyWork**](https://rudefox.io/blog/2020-07-16-show-my-work.html) is a feature of Burrow that enables non-technical end-users to audit the seed generation process in order to verify that the generated seed is derived directly from [8-sided dice](https://www.amazon.com/dp/B07XPMV4DQ/) rolls and a set of lookup-tables. Read more [here](https://rudefox.io/blog/2020-07-16-show-my-work.html).
## Getting Started
If you simply want to dive in and try your hand at generating a self-audited seed, see the [Burrow Quick Start](https://www.rudefox.io/burrow/quick-start.html) guide.
## Build
### Linux
* Install the Java 8 SDK (Java 8+ is not already installed)
```bash
[email protected]:~$ burrow mnemonic -i8 --bits 128
Input 11 x 8-sided dice rolls [1-8]: 12345678123
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 | 2 | 3 |
|000 001 010 01 | 1 100 101 110 1 | 11 000 001 010|
| 1. ahead | 2. slight | 3. scout |
Input 11 x 8-sided dice rolls [1-8]: 12345678123
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 | 2 | 3 |
|000 001 010 01 | 1 100 101 110 1 | 11 000 001 010|
| 4. ahead | 5. slight | 6. scout |
...
ahead slight scout ahead slight scout ahead slight scout ahead slight scan
```
## Build Instructions
#### Linux
* Install dependencies: Java 8
```bash
apt install openjdk-8-jdk
sudo apt-get install -y openjdk-8-jdk-headless
```
* Clone the repository and build
```bash
[email protected]:~$ git clone https://git.rudefox.io/rudefox/burrow.git
[email protected]:~$ cd burrow
[email protected]:~$ ./gradlew build distTar
git clone https://git.rudefox.io/rudefox/burrow.git
cd burrow
./gradlew build distTar
```
* Find the distribution `.tar` file in `build/distributions/`
## Quick Raspbery Pi Install
* Download the latest image [here](https://repo.rudefox.io/service/rest/v1/search/assets/download?sort=version&group=io.rudefox&name=burrow-pi-img&maven.extension=zip)
* Unzip the image file
* Flash it onto an SD Card
* [Linux](https://www.raspberrypi.org/documentation/installation/installing-images/linux.md)
* [Mac OS](https://www.raspberrypi.org/documentation/installation/installing-images/mac.md)
* [Windows](https://www.raspberrypi.org/documentation/installation/installing-images/windows.md)
* [Chrome OS](https://www.raspberrypi.org/documentation/installation/installing-images/chromeos.md)
* Insert the SD card into the Rasberry Pi and power it up
* **IMPORTANT**: Wait for the device to boot and then wait for it to automatically reboot **TWICE** (once to expand the filesystem and again to activate the read-only filesystem)
* Find the distribution `.tar` file in `build/distributions/`
+3 -2
View File
@@ -25,7 +25,7 @@ application {
def isRelease = versionDetails().commitDistance == 0 &&
versionDetails().isCleanTag &&
versionDetails().branchName == 'master'
((versionDetails().branchName == 'master') || (versionDetails().branchName == 'null'))
version isRelease ? gitVersion.call() : gitVersion.call() + "-${versionDetails().branchName}-SNAPSHOT"
@@ -46,9 +46,10 @@ tasks.withType(Test) {
}
dependencies {
compile 'io.rudefox:vixen:0.0.2'
compile 'io.rudefox:vixen:0.0.3'
compile 'info.picocli:picocli:4.5.1'
compile 'com.google.zxing:core:3.4.0'
compile 'com.diogonunes:JColor:5.0.0'
testCompile 'com.bjdweck.test:commons-test:0.0.1'
testCompile "org.junit.jupiter:junit-jupiter-params:$junitVersion"
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
@@ -1,23 +1,32 @@
package io.rudefox.burrow;
import com.bjdweck.bitcoin.mnemonic.Entropy;
import com.diogonunes.jcolor.AnsiFormat;
import java.util.Scanner;
import java.util.regex.Pattern;
import static com.diogonunes.jcolor.Attribute.*;
public class Dice8EntropyGenerator {
public static final AnsiFormat RED_STYLE = new AnsiFormat(WHITE_TEXT(), RED_BACK(), BOLD());
public static final AnsiFormat GREEN_STYLE = new AnsiFormat(BLACK_TEXT(), GREEN_BACK(), BOLD());
public static final AnsiFormat BLUE_STYLE = new AnsiFormat(WHITE_TEXT(), BLUE_BACK(), BOLD());
public static final int DICE_PER_ROLL = 11;
private final int targetBitsOfEntropy;
private final Scanner inputScanner;
private final boolean ansiColorOutput;
private Entropy entropy = new Entropy();
public Dice8EntropyGenerator(int targetBitsOfEntropy, Scanner inputScanner) {
public Dice8EntropyGenerator(int targetBitsOfEntropy, Scanner inputScanner, boolean ansiColorOutput) {
this.targetBitsOfEntropy = targetBitsOfEntropy;
this.inputScanner = inputScanner;
this.ansiColorOutput = ansiColorOutput;
}
Entropy generate() {
@@ -81,18 +90,42 @@ public class Dice8EntropyGenerator {
int entropyBitIndex = entropyBitString.length() - currentRollSetBitString.length() + rollSetBitIndex;
if (entropyBitIndex < targetBitsOfEntropy)
rollSetBitsLine.append(currentRollSetBitString.charAt(rollSetBitIndex));
rollSetBitsLine.append(styleBit("" + currentRollSetBitString.charAt(rollSetBitIndex), entropyBitIndex, rollSetBitIndex));
else
rollSetBitsLine.append("-");
if (rollSetBitIndex == 32) rollSetBitsLine.append("|");
else if (rollSetBitIndex % 3 == 2) rollSetBitsLine.append(" ");
else if (rollSetBitIndex % 11 == 10) rollSetBitsLine.append(" | ");
if (rollSetBitIndex == 32)
rollSetBitsLine.append("|");
else if (rollSetBitIndex % 3 == 2)
rollSetBitsLine.append(styleBit(" ", entropyBitIndex, rollSetBitIndex));
else if (rollSetBitIndex % 11 == 10)
rollSetBitsLine.append(" | ");
}
return rollSetBitsLine;
}
private String styleBit(String bit, int globalEntropyBitIndex, int currentRollSetBitIndex) {
if (!ansiColorOutput || globalEntropyBitIndex >= targetBitsOfEntropy)
return bit;
return getBitFormat(currentRollSetBitIndex).format(bit);
}
private AnsiFormat getBitFormat(int rollSetBitIndex) {
int wordBitIndex = rollSetBitIndex % 11;
if (wordBitIndex == 0)
return RED_STYLE;
if (wordBitIndex <= 6)
return GREEN_STYLE;
return BLUE_STYLE;
}
private String getSeedWordsLine(int rollSet) {
int baseIndex = rollSet * 3;
@@ -85,7 +85,7 @@ public class MnemonicCommand implements Runnable {
return getDice6EntropyInteractive(diceEventBuffer);
if (isDice8InteractiveMode())
return new Dice8EntropyGenerator(targetBitsOfEntropy, new Scanner(System.in)).generate();
return new Dice8EntropyGenerator(targetBitsOfEntropy, new Scanner(System.in), CommandLine.Help.Ansi.AUTO.enabled()).generate();
diceEventBuffer.appendEvents(entropyOptions.eventMethod.getEventString);
return diceEventBuffer.toEntropy();
@@ -10,6 +10,8 @@ class mnemonic_8_sided_dice_tests extends CliTestFixture {
@Test
void with_arguments_interactive_8_sided_dice_should_generate_mnemonic_sentence() throws UnsupportedEncodingException {
System.setProperty("picocli.ansi", "false");
withArgs("mnemonic -i8 --bits 128");
expectedOutput("Input 11 x 8-sided dice rolls [1-8]: ");