shamir

package module
v0.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2024 License: MIT Imports: 9 Imported by: 0

README

Shamir Secret Sharing

This is a practical example of Shamir's secret sharing.

This tool allows you to divide up a secret string S into n shares where any k of the shares will allow you to reconstruct the original secret S. If you have fewer than k of the shares, you will have no information (other than the length of the secret) about what that secret is.

Usage

To distribute a string, use the command

shamir distribute string "<secret string>" -n <number of shares to produce> -k <minimum number of shares to reconstruct the secret>

n shares will be printed to the terminal.

We can reconstruct the secret by using

shamir reconstruct string "<secret 1>" "<secret 2>" ...

As long as we provide k shares, the secret will then be printed to the terminal. Otherwise, garbage will be printed to the terminal.

Example

Say we run shamir distribute string "This is a secret." -n=5 -k=3. Something like the following could be printed to the screen:

shamir-ZDUIQPAX-11d-1-5dxDU36YEiGQmcX3tCfJlHg
shamir-ZDUIQPAX-11d-2-wzJianU+jsC3xr1O5qPj6W8
shamir-ZDUIQPAX-11d-3-coZISivP78FGfwvcMfZPCTk
shamir-ZDUIQPAX-11d-4-4GAeOAldaFJ07zR7rDxfTj8
shamir-ZDUIQPAX-11d-5-UdQ0GFesCVOFVoLpe2nzrmk

The prefix shamir- indicates that this is a share in Shamir's secret sharing scheme. ZDUIQPAX is a randomly generated ID that allows you to correlate shares to the same secret. 11d is the primitive polynomial used to construct the underlying Galois field. 1 is the x coordinate of the share. The remaining text is base64-encoded data. Each byte corresponds to the value of a polynomial evaluated at the corresponding x-coordinate of the share. (Note that each byte is encoded separately, each with a randomly-generated polynomial.)

To reconstruct the message, simply run shamir reconstruct with any three of the five shares.

For example, using shares 1, 4, and 5, we would run the command

shamir reconstruct string "shamir-ZDUIQPAX-11d-4-4GAeOAldaFJ07zR7rDxfTj8" "shamir-ZDUIQPAX-11d-5-UdQ0GFesCVOFVoLpe2nzrmk" "shamir-ZDUIQPAX-11d-1-5dxDU36YEiGQmcX3tCfJlHg"

We get the following output:

ZDUIQPAX:
This is a secret.

Note that the order in which we supply the shares is irrelevant.

If we try to only use shares 4 and 5, we cannot reconstruct the message, and we get gibberish:

ZDUIQPAX:
���l��V�1�      �u��z
Sharing Files

A similar process to the one described above can be performed to use this scheme on a file.

To distribute a file, use shamir distribute file <filename> with an appropriate -n and -k. This will produce n .txt files in your current directory.

To reconstruct the secret, run shamir reconstruct file in a directory with at least k of the shares to reconstruct the secret. The secret will be saved to a file. The filename is secret-<secret id> with no extension. Note that the original filename will be lost!

Actually Distributing These Shares

You can export these shares as QR codes, wallet-sized cards, text files, or on a printable sheet of paper.

QR Code Support

To make distribution of shares easier in the real world, you can use the --qr flag to save each share as a unique QR code. This will produce n ID card sized SVGs that are easy to print.

Printable Card Support

You can distribute shares as ID-card-sized cards using the --card flag. This produces an SVG for each share.

Text File Support

You can save the shares to txt files using the --file flag. This way you don't have to manually copy/paste the shares from the terminal.

Printable SVG Support

If you would like to print out the shares on a single sheet of paper, use the --print option to create a printable SVG. Just be aware that this could open you up to security vulnerabilities during the printing process, as all shares will be in one place. And be sure to delete the SVG file once you print it!

Build Notes

The following scripts are what I use to cross-compile this software.

From Windows 11 PowerShell
$version = "v<major>_<minor>_<patch>"

$env:GOOS = "windows"; $env:GOARCH = "amd64"; $filename = "shamir-$env:GOOS-$env:GOARCH-$VERSION.exe"; go build -o $filename

$env:GOOS = "linux"; $env:GOARCH = "amd64"; $filename = "shamir-$env:GOOS-$env:GOARCH-$VERSION"; go build -o $filename
$env:GOOS = "linux"; $env:GOARCH = "arm64"; $filename = "shamir-$env:GOOS-$env:GOARCH-$VERSION"; go build -o $filename

$env:GOOS = "darwin"; $env:GOARCH = "arm64"; $filename = "shamir-$env:GOOS-$env:GOARCH-$VERSION"; go build -o $filename
$env:GOOS = "darwin"; $env:GOARCH = "amd64"; $filename = "shamir-$env:GOOS-$env:GOARCH-$VERSION"; go build -o $filename
From Linux Bash
#!/bin/bash

OUTPUT_NAME="shamir"
GOOS="${1:-linux}"
GOARCH="${2:-amd64}"
VERSION="${3:v0_0_0}"

# Build the executable
filename="${OUTPUT_NAME}-${GOOS}-${GOARCH}-${VERSION}"
if [ "$GOOS" = "windows" ]; then
    filename="${filename}.exe"
fi

GOARCH=$GOARCH GOOS=$GOOS go build -o "$filename"

echo "Build complete: $filename"

Documentation

Index

Constants

View Source
const SharePrefix string = "shamir"

Variables

View Source
var ErrDuplicateShare error = errors.New("duplicate shares provided")
View Source
var ErrInconsistentLength error = errors.New("length of shares is inconsistent")
View Source
var ErrMismatchedSecretID error = errors.New("secret ID's don't match")
View Source
var ErrNonPrimitivePolynomial error = errors.New("supplied polynomial cannot be primitive")
View Source
var ErrThresholdTooLarge error = errors.New("threshold cannot exceed number of shares")

Functions

func ComputeDegree

func ComputeDegree(poly int) int

computes the degree of a given polynomial

func RecoverSecret

func RecoverSecret(shares []Share) ([]byte, error)

Types

type Gf2m

type Gf2m struct {
	// contains filtered or unexported fields
}

func NewField

func NewField(primitivePoly int) Gf2m

func (Gf2m) Add

func (field Gf2m) Add(a, b GfElement) GfElement

add two elements in the field

func (Gf2m) Divide

func (field Gf2m) Divide(a, b GfElement) (GfElement, error)

divide a by b

func (Gf2m) EvaluatePolynomial

func (field Gf2m) EvaluatePolynomial(p []GfElement, x GfElement) (y GfElement)

evaluate a polynomial over a field

func (Gf2m) GetNelements

func (field Gf2m) GetNelements() int

func (Gf2m) Multiply

func (field Gf2m) Multiply(a, b GfElement) GfElement

multiply two elements in the field

func (Gf2m) String

func (field Gf2m) String() string

func (Gf2m) Subtract

func (field Gf2m) Subtract(a, b GfElement) GfElement

subtract two elements in the field addition and subtraction are the same in GF(2^m)

type GfElement

type GfElement int

type GfPower

type GfPower int

type Shamir

type Shamir struct {
	// contains filtered or unexported fields
}

func NewShamirSecret

func NewShamirSecret(primitivePoly int, nshares int, threshold int, secret []byte) (*Shamir, error)

func (Shamir) GetId added in v0.2.1

func (shamir Shamir) GetId() string

func (Shamir) GetShares

func (shamir Shamir) GetShares() []Share

func (Shamir) ShareString

func (shamir Shamir) ShareString(n int) string

func (Shamir) String

func (shamir Shamir) String() string

type Share

type Share struct {
	// contains filtered or unexported fields
}

func NewShare

func NewShare(secret_id string, primitivePoly int64, x GfElement, y []GfElement) Share

func NewSharesFromString

func NewSharesFromString(input string) ([]Share, error)

func (Share) GetPrimitivePoly

func (share Share) GetPrimitivePoly() int64

func (Share) GetSecretId

func (share Share) GetSecretId() string

func (Share) GetXString

func (share Share) GetXString() string

func (Share) GetYString

func (share Share) GetYString() string

func (Share) ShareLabel

func (share Share) ShareLabel() string

func (Share) String

func (share Share) String() string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL