Skip to content

Commit

Permalink
Merge pull request #6 from xkortex/dev/dev
Browse files Browse the repository at this point in the history
Dev/dev
  • Loading branch information
xkortex authored May 12, 2020
2 parents ffee322 + d072d15 commit b96f184
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 133 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
build/*
Dockerfile
28 changes: 18 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
VERSION := $(shell git describe --always --dirty --tags)

.PHONY: default get test all

default: get
go build -i -ldflags="-X 'main.Version=${VERSION}'" -o ${GOPATH}/bin/passcrux

get:
go get

default: get
go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o ${GOPATH}/bin/passcrux
test: default
bash ./tests/end2end.sh

fmt:
go fmt ./...

static: get
CGO_ENABLED=0 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o ${GOPATH}/bin/passcrux
CGO_ENABLED=0 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o ${GOPATH}/bin/passcrux

linux_86:
GOOS=linux GOARCH=386 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-linux_386
GOOS=linux GOARCH=386 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-linux_386

linux_64:
GOOS=linux GOARCH=amd64 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-linux_amd64
GOOS=linux GOARCH=amd64 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-linux_amd64

linux_arm:
GOOS=linux GOARCH=arm go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-linux_arm
GOOS=linux GOARCH=arm go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-linux_arm

linux_arm64:
GOOS=linux GOARCH=arm64 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-linux_arm64
GOOS=linux GOARCH=arm64 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-linux_arm64

freebsd_64:
GOOS=freebsd GOARCH=amd64 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-freebsd_amd64
GOOS=freebsd GOARCH=amd64 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-freebsd_amd64

darwin_64:
GOOS=darwin GOARCH=amd64 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-darwin_amd64
GOOS=darwin GOARCH=amd64 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-darwin_amd64

windows:
GOOS=windows GOARCH=amd64 go build -i -ldflags="-X 'main.Version=v${VERSION}'" -o build/passcrux-windows_amd64
GOOS=windows GOARCH=amd64 go build -i -ldflags="-X 'main.Version=${VERSION}'" -o build/passcrux-windows_amd64



40 changes: 26 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
# passcrux
PassCrux - never lose your soul again!
PassCrux - Immortalize your master password!

[![Build Status](https://travis-ci.com/xkortex/passcrux.svg?branch=master "Travis CI status")](https://travis-ci.com/xkortex/passcrux.svg?branch=master)
[![Build Status](https://travis-ci.com/xkortex/passcrux.svg?branch=master)](https://travis-ci.com/xkortex/passcrux)
[![GoDoc](https://godoc.org/github.com/xkortex/passcrux?status.svg)](https://godoc.org/github.com/xkortex/passcrux)
[![Go Report Card](https://goreportcard.com/badge/github.com/xkortex/passcrux)](https://goreportcard.com/report/github.com/xkortex/passcrux)

If you are like me, you loathe single points of failure, *especially* when it comes to passwords,
and *extra-especially* when it comes to "master" passwords which guard things like password managers.
Some password managers have mechanism to reset your password, however ever password reset route is an
and **extra-especially** when it comes to "master" passwords which guard things like password managers.
Some password managers have mechanisms to reset your password, however every password reset-function is an
increased attack surface. Plus, there is always the spectre of a password manager provider going under,
or getting hacked, or whatever. I wanted a way to back up my "master" passwords under my own terms.

PassCrux gets to the crux of this matter, and has only a transient resemblance to crux-sounding recovery
schemes found in some magical literature ;). It works by separating your password - or any data - into shards,
that you can do anything you want with, just provide M of the N shards and you can recover the original data.
that you can do anything you want with. Just provide `M` of the `N` shards and you can recover the original data.
If you haven't been living in a cursed cave for the past two decades, you'll recognize this as
[Shamir's Secret Sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing) algo, which is indeed
at the heart of this tool. It's basically a lightweight wrapper around SSS with built-in helpers and formatters.
[Shamir's Secret Sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing) algorithm, which is indeed
at the heart of this tool. It's basically a lightweight wrapper around SSS, with built-in helpers and formatters
for storing the shards in human-readable format.

# Testimonials
## Testimonials

> Heck, that sounds so fun! I can't wait to lose my master password!
-- [aeksco](https://github.com/aeksco)
Expand All @@ -27,11 +28,11 @@ at the heart of this tool. It's basically a lightweight wrapper around SSS with
> bosses, and you've got yourself a solid adventure.
-- [erotemic](https://github.com/erotemic)

# Usage
## Usage

To split a password from a prompt, into 5 shards with 3 needed to reconstruct, enter
```bash
passcrux split -r 3/5 -p
passcrux split --ratio 3/5 --prompt
```

Out:
Expand All @@ -43,6 +44,7 @@ f3ab8d463e182893
e4ea839978cc8eae
```

Now, distribute your shards. In this case, we are just going to dump them into a file for this demo.
Copy (at least) 3 of the 5 output shards and paste into a file, `shards.txt`, one shard string per line.

`shards.txt`
Expand All @@ -52,18 +54,26 @@ a38f786f19680cb3
e4ea839978cc8eae
```

Then run:
Then run this command to print the secret:
```bash
cat shards.txt | passcrux combine --stdin
cat shards.txt | passcrux combine
```

# Building/Installation
## What to do with shards?
That's entirely up to you! Get creative with it! Here are some ideas to get your ideas churning:
- Stamp them into metal. Hide them in various places. Make a good ol' fashioned pirate map 🏴‍☠️
- Use `--enc abc` and mark the letters in your favorite books 📚
- Convert hexadecimal values into notes and make some sweet guitar riffs 🎸
- Give a copy to `M` trusted friends with instructions to delete your browser history 🗑️


## Building/Installation

#### Turbo-instant docker usage:

```docker run --rm -it xkortex/passcrux [OPTIONS]```

Note: `-it` is required for `-p/--pass` (interactive password prompt) and `-v` for any file-I/O.
Note: `-it` is required for `-p/--prompt` (interactive password prompt) and `-v` for any file-I/O.

#### Conventional:

Expand All @@ -75,9 +85,11 @@ Requires a typical golang environment. Simply run `make` to compile `passcrux` t
- [x] "abc" encoding
- [x] Stabilize pipe-in interface and flags
- [ ] validate/ensure correct behavior with DOS-style carriage returns `\r and \r\n`
- [ ] test on windows
- [x] Travis / CI hooks
- [x] Dockerfile
- [ ] standardize output formatter interface
- [ ] goexpect for testing interactive password prompt
- [ ] config parsing
- [ ] handling for raw bytes I/O

Expand Down
78 changes: 0 additions & 78 deletions cmd/demo.go

This file was deleted.

2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func init() {
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
RootCmd.PersistentFlags().BoolP("silent", "S", false, "Suppress errors")
RootCmd.PersistentFlags().BoolP("pass", "p", false, "Read key/password from standard in prompt")
RootCmd.PersistentFlags().BoolP("prompt", "p", false, "Read key/password from standard in prompt")
RootCmd.PersistentFlags().BoolP("dummy", "D", false, "Testing")

// Formatting parameters
Expand Down
48 changes: 28 additions & 20 deletions cmd/split.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

// Get the password/phrase/key from input
// todo: deal with extra character trim issue
// todo: figure out what I meant by "character trim issue"
func getKeyData(args []string, useRaw bool, usePass bool) (string, error) {
stdin_struct, err := common.Get_stdin()
if err != nil {
Expand Down Expand Up @@ -53,20 +54,20 @@ func getKeyData(args []string, useRaw bool, usePass bool) (string, error) {
return temp, nil
}

func ParseSplitSettings(settings *common.SplitSettings, cmd *cobra.Command) error {
func ParseSplitSettings(cmd *cobra.Command) (settings common.SplitSettings, err error) {
ratioArg, _ := cmd.Flags().GetString("ratio")
re := regexp.MustCompile(`(\d+)[/|:](\d+)`)
match := re.FindSubmatch([]byte(ratioArg))
if len(match) != 3 {
return fmt.Errorf("Unable to parse `ratio` argument: '%s'", ratioArg)
return settings, fmt.Errorf("Unable to parse `ratio` argument: '%s'", ratioArg)
}
a, err := strconv.ParseInt(string(match[1]), 10, 32)
if err != nil {
return err
return settings, err
}
b, err := strconv.ParseInt(string(match[2]), 10, 32)
if err != nil {
return err
return settings, err
}
vprint.Printf("a: %d b: %d\n", a, b)
var threshold, parts int64
Expand All @@ -79,11 +80,23 @@ func ParseSplitSettings(settings *common.SplitSettings, cmd *cobra.Command) erro
}

if threshold < 2 || parts < 2 || threshold > 256 || parts > 256 {
return fmt.Errorf("parts and threshold must be 2 < x < 256")
return settings, fmt.Errorf("parts and threshold must be 2 < x < 256")
}
settings.Parts = int(parts)
settings.Threshold = int(threshold)
return nil
return settings, nil
}

func PasscruxSplit(secret []byte, splitSettings common.SplitSettings, formatSettings common.FormatSettings) (string, error) {
vprint.Print("Splittings: \n ", splitSettings, " : \n")

vprint.Printf("Len in bytes: %d\n", len(secret))
shards, err := shamir.Split(secret, splitSettings.Parts, splitSettings.Threshold)
common.LogIfFatal(err)
vprint.Printf("Len of each shard in bytes: %d\n", len(shards[0]))
vprint.Print("Output:\n")
stringShards := common.FormatShards(shards, formatSettings)
return strings.Join(stringShards, formatSettings.RecordSep), nil
}

var splitCmd = &cobra.Command{
Expand All @@ -97,26 +110,21 @@ Ratio is "M/N"
var err error
vprint.Print("Run subcmd: split\n")

usePass, _ := cmd.Flags().GetBool("pass")
pass, err := getKeyData(args, false, usePass)
usePrompt, _ := cmd.Flags().GetBool("prompt")
splitSettings, err := ParseSplitSettings(cmd)
common.LogIfFatal(err)
splittings := common.SplitSettings{}
err = ParseSplitSettings(&splittings, cmd)
vprint.Print("Splittings: \n ", splittings, " : ", err, "\n")
formatSettings, err := common.ParseFormatSettings(cmd)
common.LogIfFatal(err)

secret := []byte(pass)
vprint.Printf("Len in bytes: %d\n", len(secret))
vprint.Printf("Input: %s\n", pass)
shards, err := shamir.Split(secret, splittings.Parts, splittings.Threshold)
secretString, err := getKeyData(args, false, usePrompt)
common.LogIfFatal(err)
vprint.Printf("Len of each shard in bytes: %d\n", len(shards[0]))
vprint.Print("Output:\n")
settings, err := common.ParseFormatSettings(cmd)
vprint.Printf("Input: %s\n", secretString)

secret := []byte(secretString)
out, err := PasscruxSplit(secret, splitSettings, formatSettings)
common.LogIfFatal(err)
out, err := common.FormatShards(shards, settings)
fmt.Println(out)

fmt.Println(out)
},
}

Expand Down
8 changes: 8 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type FormatSettings struct {
EncodingType string // binary-to-string encoding, e.g. hex, base32
Sep string // separator between bytes
RecordSep string // separator between records/shards
FieldSize int // size of each field, eg 2-> DE:AD:BE:EF
FilenamePat string // pattern (in typical sprintf notation) for filenames
}

Expand Down Expand Up @@ -97,6 +98,13 @@ func ParseFormatSettings(cmd *cobra.Command) (settings FormatSettings, err error
settings.RecordSep = recordSep
}

fieldSize, err := cmd.Flags().GetInt("fieldsize")
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse argument `fieldsize`, defaulting to 2")
} else {
settings.FieldSize = fieldSize
}

return settings, nil
}

Expand Down
Loading

0 comments on commit b96f184

Please sign in to comment.