diff --git a/sssa.go b/sssa.go index ac2c798..d0d54fc 100644 --- a/sssa.go +++ b/sssa.go @@ -20,6 +20,16 @@ const ( * share to recreate, of length shares, from the input secret raw as a string **/ func Create(minimum int, shares int, raw string) ([]string, error) { + return CreateFromBytes(minimum, shares, []byte(raw)) +} + +/** + * Returns a new arary of secret shares (encoding x,y pairs as base64 strings) + * created by Shamir's Secret Sharing Algorithm requring a minimum number of + * share to recreate, of length shares, from the input secret raw as an array + * bytes +**/ +func CreateFromBytes(minimum int, shares int, raw []byte) ([]string, error) { // Verify minimum isn't greater than shares; there is no way to recreate // the original polynomial in our current setup, therefore it doesn't make // sense to generate fewer shares than are needed to reconstruct the secret. @@ -28,7 +38,7 @@ func Create(minimum int, shares int, raw string) ([]string, error) { } // Convert the secret to its respective 256-bit big.Int representation - var secret []*big.Int = splitByteToInt([]byte(raw)) + var secret []*big.Int = splitByteToInt(raw) // Set constant prime across the package prime, _ = big.NewInt(0).SetString(DefaultPrimeStr, 10) @@ -110,7 +120,7 @@ func Create(minimum int, shares int, raw string) ([]string, error) { * or more are passed to this function. Passing thus does not affect it * Passing fewer however, simply means that the returned secret is wrong. **/ -func Combine(shares []string) (string, error) { +func CombineAsBytes(shares []string) ([]byte, error) { // Recreate the original object of x, y points, based upon number of shares // and size of each share (number of parts in the secret). var secrets [][][]*big.Int = make([][][]*big.Int, len(shares)) @@ -122,7 +132,7 @@ func Combine(shares []string) (string, error) { for i := range shares { // ...ensure that it is valid... if IsValidShare(shares[i]) == false { - return "", ErrOneOfTheSharesIsInvalid + return []byte(""), ErrOneOfTheSharesIsInvalid } // ...find the number of parts it represents... @@ -183,7 +193,21 @@ func Combine(shares []string) (string, error) { } // ...and return the result! - return string(mergeIntToByte(secret)), nil + return mergeIntToByte(secret), nil +} + +/** + * Takes a string array of shares encoded in base64 created via Shamir's + * Algorithm; each string must be of equal length of a multiple of 88 characters + * as a single 88 character share is a pair of 256-bit numbers (x, y). + * + * Note: the polynomial will converge if the specified minimum number of shares + * or more are passed to this function. Passing thus does not affect it + * Passing fewer however, simply means that the returned secret is wrong. +**/ +func Combine(shares []string) (string, error) { + res, err := CombineAsBytes(shares) + return string(res), err } /** diff --git a/sssa_test.go b/sssa_test.go index 389f7a9..1f12d33 100644 --- a/sssa_test.go +++ b/sssa_test.go @@ -2,6 +2,7 @@ package sssa import ( "testing" + "bytes" ) func TestCreateCombine(t *testing.T) { @@ -30,6 +31,32 @@ func TestCreateCombine(t *testing.T) { } } +func TestCreateCombineBytes(t *testing.T) { + // Short, medium, and long tests + testvals := [][]byte{ + []byte("N17FigASkL6p1EOgJhRaIquQLGvYV0"), + []byte("0y10VAfmyH7GLQY6QccCSLKJi8iFgpcSBTLyYOGbiYPqOpStAf1OYuzEBzZR"), + []byte("KjRHO1nHmIDidf6fKvsiXWcTqNYo2U9U8juO94EHXVqgearRISTQe0zAjkeUYYBvtcB8VWzZHYm6ktMlhOXXCfRFhbJzBUsXaHb5UDQAvs2GKy6yq0mnp8gCj98ksDlUultqygybYyHvjqR7D7EAWIKPKUVz4of8OzSjZlYg7YtCUMYhwQDryESiYabFID1PKBfKn5WSGgJBIsDw5g2HB2AqC1r3K8GboDN616Swo6qjvSFbseeETCYDB3ikS7uiK67ErIULNqVjf7IKoOaooEhQACmZ5HdWpr34tstg18rO"), + } + + minimum := []int{4, 6, 20} + shares := []int{5, 100, 100} + + for i := range testvals { + created, err := CreateFromBytes(minimum[i], shares[i], testvals[i]) + if err != nil { + t.Fatal("Fatal: creating: ", err) + } + combined, err := CombineAsBytes(created) + if err != nil { + t.Fatal("Fatal: combining: ", err) + } + if !bytes.Equal(combined, testvals[i]) { + t.Fatal("Fatal: combining returned invalid data") + } + } +} + func TestLibraryCombine(t *testing.T) { shares := []string{ "U1k9koNN67-og3ZY3Mmikeyj4gEFwK4HXDSglM8i_xc=yA3eU4_XYcJP0ijD63Tvqu1gklhBV32tu8cHPZXP-bk=",