Skip to content

a practical example of Shamir's secret sharing scheme

License

Notifications You must be signed in to change notification settings

49pctber/shamir

Repository files navigation

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"