From 5aaa3e7361c17cad0ce3887422ceb7df7ade9d64 Mon Sep 17 00:00:00 2001 From: "Ethan L. Miller" Date: Wed, 2 Sep 2020 16:29:38 -0700 Subject: [PATCH] gfalg generates and recovers a secret via Shamir Secret Sharing! --- gfalg.py | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/gfalg.py b/gfalg.py index e69de29..d741ca8 100644 --- a/gfalg.py +++ b/gfalg.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +import sys +import secrets +from galois import GaloisNumber as GN +import galois +from collections import namedtuple + +gf = galois.GaloisFieldLog (8) + +def _gf_unpack (v): + return tuple(GN(b, gf) for b in v) +def _gf_pack (v): + return b''.join ([b.to_bytes() for b in v]) + +class Secret: + value_len = 32 + def __init__ (self, value = None): + if not value: + self.value = secrets.token_bytes (Secret.value_len) + elif type(value) == str: + self.value = bytes.fromhex (value) + elif type(value) == bytes: + self.value = value + else: + raise ValueError("Secret must be bytes or hex string") + if len (self.value) != Secret.value_len: + raise ValueError("Secret must be exactly {0} bytes long".format (Secret.value_len)) + def __str__ (self): + return self.value.hex () + def __repr__ (self): + return str(self) + def __len__ (self): + return len (self.value) + +class SSS_Share: + def __init__ (self, share_id, secret): + if not 0 < share_id < 254: + raise ValueError("Invalid share ID") + if type(secret) != Secret: + raise ValueError ("Invalid secret") + self.share_id = share_id + self.secret = secret + def __str__ (self): + return 'ID {0:2}: {1}'.format (self.share_id, self.secret) + def __repr__ (self): + return str(self) + +def _lagrange_interpolate (x, shares): + pass + +def sss_generate_shares (secret, min_shares, share_ids): + if any ([not 1 <= x <= 254 for x in share_ids]): + raise ValueError ("Share IDs must be between 1-254") + coeff = list() + coeff.append (_gf_unpack (secret.value)) + for i in range (0, min_shares-1): + coeff.append (_gf_unpack (Secret().value)) + shares = list() + for i in share_ids: + v = GN(i, gf) + m = GN(1, gf) + accum = [GN(0, gf)] * len (secret) + for a in coeff: + accum = m.mul_region (a, accum) + m *= v + shares.append (SSS_Share(i, Secret (_gf_pack(accum)))) + return shares + + +def sss_recover_secret (shares): + shrs = tuple (_gf_unpack (s.secret.value) for s in shares) + ids = tuple (GN(x.share_id, gf) for x in shares) + accum = [GN(0, gf)] * len(shares[0].secret) + for (x, shr) in zip (ids, shrs): + prod = GN(1, gf) + for i in ids: + if i != x: + prod *= i / (i - x) + accum = prod.mul_region (shr, accum) + return Secret (_gf_pack (accum)) + +def sss_generate_new_share (shares, share_id): + pass +