|
package main |
|
|
|
import ( |
|
"crypto/rand" |
|
"fmt" |
|
"log" |
|
|
|
"github.com/wybiral/tshare" |
|
"golang.org/x/crypto/nacl/secretbox" |
|
) |
|
|
|
func main() { |
|
// plaintext secret |
|
plaintext := []byte("Hello world!") |
|
// generate random secret key |
|
var key [32]byte |
|
rand.Read(key[:]) |
|
// generate random nonce |
|
var nonce [24]byte |
|
rand.Read(nonce[:]) |
|
// encrypt plaintext using nonce and key |
|
encrypted := secretbox.Seal(nil, plaintext, &nonce, &key) |
|
// split key into shares |
|
shares, err := tshare.SplitBytes(key[:]) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
// demonstrate key recovery from all valid combinations of shares |
|
recover(shares[0], shares[1], encrypted, nonce) |
|
recover(shares[1], shares[0], encrypted, nonce) |
|
recover(shares[0], shares[2], encrypted, nonce) |
|
recover(shares[2], shares[0], encrypted, nonce) |
|
recover(shares[1], shares[2], encrypted, nonce) |
|
recover(shares[2], shares[1], encrypted, nonce) |
|
} |
|
|
|
func recover(a, b, encrypted []byte, nonce [24]byte) { |
|
var key [32]byte |
|
// join shares |
|
joined, err := tshare.JoinBytes(a, b) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
// copy joined shares to key |
|
copy(key[:], joined) |
|
// decrypt encrypted message using nonce and recovered key |
|
decrypted, ok := secretbox.Open(nil, encrypted, &nonce, &key) |
|
if !ok { |
|
log.Fatal("unable to decrypt") |
|
} |
|
// print share tags used to recover key and decrypted message |
|
fmt.Printf("%d,%d: %s\n", a[0], b[0], string(decrypted)) |
|
} |