diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8cc6b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +./cmd/sss/sss diff --git a/README.md b/README.md index 4dddcfe..7f9d6b9 100644 --- a/README.md +++ b/README.md @@ -33,17 +33,23 @@ func main() { } ``` -Also see the two example programs in the `example` directory: +Install `cmd/sss` to use the command line interface: + + go install github.com/kyodo-tech/shamir/cmd/sss@latest + +Then run `sss` to split a secret into shares and combine them to reconstruct the secret: ```sh -go run example/split.go "my secret" +Usage: sss -mode=split -secret= -n= -T= +# Example: +sss -secret "my secret" # Output: -# Share 0: lK8LyefHjxzOAQ== -# Share 1: 1Ws3IGJh/lVQAg== -# Share 2: LL0cmuDFAyzqAw== -# Share 3: Wf8RJQs43iALBA== -# Share 4: oCk6n4mcI1mxBQ== -go run ./example/combine.go lK8LyefHjxzOAQ==,LL0cmuDFAyzqAw==,oCk6n4mcI1mxBQ== +# N8QLmd6YcLu2AQ== +# Nnubhbvx52y8Ag== +# bMawbwAK5bJ+Aw== +# SurUYDi7Mfm4BA== +# EFf/ioNAMyd6BQ== +sss -mode combine -shares N8QLmd6YcLu2AQ==,bMawbwAK5bJ+Aw==,EFf/ioNAMyd6BQ== # Output: -# Reconstructed secret: my secret +# my secret ``` diff --git a/cmd/sss/main.go b/cmd/sss/main.go new file mode 100644 index 0000000..08b6df0 --- /dev/null +++ b/cmd/sss/main.go @@ -0,0 +1,80 @@ +package main + +import ( + "bufio" + "encoding/base64" + "flag" + "fmt" + "os" + "strings" + + "github.com/kyodo-tech/shamir" +) + +func main() { + mode := flag.String("mode", "split", "Mode: split or combine") + secret := flag.String("secret", "", "The secret to split (for split mode)") + sharesStr := flag.String("shares", "", "Comma-separated shares (for combine mode)") + N := flag.Int("n", 5, "Total number of shares") + T := flag.Int("t", 3, "Number of shares needed to reconstruct the secret") + flag.Parse() + + switch *mode { + case "split": + if *secret == "" { + reader := bufio.NewReader(os.Stdin) + inputSecret, err := reader.ReadString('\n') + if err != nil { + fmt.Println("Error reading input:", err) + os.Exit(1) + } + inputSecret = strings.TrimSpace(inputSecret) + splitSecret(inputSecret, *N, *T) + } else { + splitSecret(*secret, *N, *T) + } + case "combine": + if *sharesStr == "" { + fmt.Println("Usage: go run main.go -mode=combine -shares=,,...,") + os.Exit(1) + } + combineShares(*sharesStr) + default: + fmt.Println("Invalid mode. Use -mode=split or -mode=combine") + os.Exit(1) + } +} + +func splitSecret(secret string, totalShares, T int) { + secretBytes := []byte(secret) + shares, err := shamir.Split(secretBytes, totalShares, T) + if err != nil { + panic(err) + } + + // Print share strings + for _, share := range shares { + fmt.Println(base64.StdEncoding.EncodeToString(share)) + } +} + +func combineShares(sharesStr string) { + shareStrs := strings.Split(sharesStr, ",") + + var shares [][]byte + for _, shareStr := range shareStrs { + share, err := base64.StdEncoding.DecodeString(shareStr) + if err != nil { + panic(err) + } + + shares = append(shares, share) + } + + reconstructed, err := shamir.Combine(shares) + if err != nil { + panic(err) + } + + fmt.Println(reconstructed) +} diff --git a/example/combine.go b/example/combine.go deleted file mode 100644 index 63757dc..0000000 --- a/example/combine.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "encoding/base64" - "fmt" - "os" - "strings" - - "github.com/kyodo-tech/shamir" -) - -func main() { - // read comma separated shares from command line - if len(os.Args) != 2 { - fmt.Println("Usage: go run main.go ,,...,") - os.Exit(1) - } - - // split shares - sharesStr := strings.Split(os.Args[1], ",") - - var shares [][]byte - for _, shareStr := range sharesStr { - share, err := base64.StdEncoding.DecodeString(shareStr) - if err != nil { - panic(err) - } - - shares = append(shares, share) - } - - // Use any 3 out of 5 shares to reconstruct the secret - reconstructed, err := shamir.Combine(shares[:3]) - if err != nil { - panic(err) - } - - fmt.Printf("Reconstructed secret: %s\n", reconstructed) -} diff --git a/example/split.go b/example/split.go deleted file mode 100644 index 855c7a5..0000000 --- a/example/split.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "encoding/base64" - "fmt" - "os" - - "github.com/kyodo-tech/shamir" -) - -func main() { - if len(os.Args) != 2 { - fmt.Println("Usage: go run main.go ") - os.Exit(1) - } - - secret := []byte(os.Args[1]) - shares, err := shamir.Split(secret, 5, 3) - if err != nil { - panic(err) - } - - // print share strings - for i, share := range shares { - fmt.Printf("Share %d: %s\n", i, base64.StdEncoding.EncodeToString(share)) - } -}