Ejemplo n.º 1
0
def split_secret(secret, no_of_splits, threshold):
    secret_data = StringIO.StringIO(secret)
    outputs = list()

    for i in xrange(no_of_splits):
        outputs.append(StringIO.StringIO())

    PySSSS.encode(secret_data, outputs, threshold)

    shares = [each_output.getvalue().encode('hex') for each_output in outputs]

    return shares
Ejemplo n.º 2
0
def splitsecret(secret, threshold, numshares):
    """returns list of shares of secret, with t=threshold, k=numshares

  splitsecret splits ``secret`` into ``numshares`` parts, with ``threshold``
  required to reconstruct the secret.

  The secret is padded to 128-character blocks to reduce information about
  the length of the secret. A CRC32 value of the raw secret is also generated (and
  included within the ciphertext) in order to ease validation of reconstruction.

  :param secret: the raw secret to be split
  :param threshold: the minimum number of shares required for successful reconstruction
  :param numshares: the number of shares to generate
  :type secret: string
  :type threshold: int
  :type numshares: int
  :returns: a list of shares
  :rtype: list of strings

  :Example:

  >>> import PySSSS
  >>> secret = "hun\0ter2" # any string will do
  >>> shares = pyssss.splitsecret(secret, 2, 3)
  >>> len(shares)
  3
  >>> shares = pyssss.splitsecret(secret, 99, 2) # n.b. threshold > numshares?

  """
    global _padlen
    global _padchar

    if threshold > numshares:
        raise ValueError("threshold {} exceeds number of shares {}".format(threshold, numshares))
    if numshares == 1:
        raise ValueError("cannot split secret into 1 part")

    # Here we track the number of characters we're padding, because the
    #  pad character is in-band.
    passlen = len(secret)
    padnum = (_padlen - (passlen % _padlen)) % _padlen
    secret = "{:0=8x}{:0=4x}{}".format(binascii.crc32(secret) & 0xFFFFFFFF, padnum, secret.rjust(_padlen, _padchar))

    outputs = []
    for i in xrange(numshares):
        outputs.append(StringIO.StringIO())

    PySSSS.encode(StringIO.StringIO(secret), outputs, threshold)

    return [outputs[i].getvalue().encode("hex") for i in xrange(numshares)]
Ejemplo n.º 3
0
def recover_secret(shares):
    shares_string_io = list()
    for i in xrange(len(shares)):
        shares_string_io.append(StringIO.StringIO())

    for i in xrange(len(shares)):
        shares_string_io[i].write(shares[i].decode('hex'))

    for i in xrange(len(shares)):
        shares_string_io[i].seek(0)

    secret = StringIO.StringIO()
    PySSSS.decode(shares_string_io, secret)
    return secret.getvalue()
Ejemplo n.º 4
0
def recoversecret(shares):
    """returns the reconstructed raw secret

  recoversecret combines the supplied list of shares and returns the raw string.

  This function raises a ``ValueError`` if the CRC32 of the reconstructed secret
  does not match the reconstructed CRC from the ciphertext.

  :param shares: a list of shares
  :type shares: list of strings
  :returns: the raw secret
  :rtype: string

  :Example:

  >>> import pyssss
  >>> shares = [
      '568cd977816ca4ab74c81e37a0d12479ce589211df5c9b2343be80208094af8d0abd8d321150eb1e69dc5d027d53862ca0cb71cf1a5a665866210259adbd2d13ad0915ee1fbfe19519a77f4f5410fa458d9ebfe9c8743881e790efefd40ad9227e8fb82d71126ed0c75511d17547a641104ae76fe66096f39bc403a9ae10142a3a29a276855fdc114d162beff38f921fa63b8a9ef18b7dfb8ecf3a7fd8c32005fd401deca8d2d81a5b3f8cc68b894a6874025b5f0283d042be369561cf024dc88284999c28bf130e2df92fb028e4a8e627f48dde019eed9b43f3fba037b220a24514bdcdab447bd37dfe638eaae603d1114b97ae0364828c1f64e6c55ff3276279991e233b7d4f900948b13b4e8bf960790e91b5bbc6502e',
      '0a2eef4acd925746e1fe58871b71dca9c39380f74f25fa940db3028dbd5ee21f86e14e2688b6ccab68597e4f3f086755a95ee09c694d596f48afd42834016860c8130ce74bcb44b8f57a4a587289591d373fcd66be1ada2958dcd5d551af2dc8b2a0ad33d19f458da32faddf1950b048b546b7af7f7ec745f341f6d4a18486a6e02af8872741040e04d6cd2b7d20244da78f79d3cfdb9850568057cc61859983a68cf9192f3744d9bf3da087e8157219570e8309fa63c25fcc17a309de0a03ec8b5ceae77efd6a24f00352b9779f2488e0753dfbc4c1a1e4d90858c1e46ef62f08896c2952ff255facbaa821d30862fbae1dbb4ba4250ab3dbcdc44b0940957c4f31d14a1893331cc4ccfc288e9f96ebe418ca6d3274e389',
      '5864be0b621e1f8d8b82adb657a1af677e87a758f7cbc24da43abc2ff405e8ee5a2244e3e53a98886a4806bc5e78795b1daf39a691c19f44b49f619336fc403e2944d141b206f6110beebd448eb9a9c26534aa52ecdcfb07ca2b2e2ed8f2c5b6c0a8fc8836a65feb80ea8251850e91666b2195d75b8f621e78f608159fe7e90df283513b71da7cba7b34765eaf1f7f6437e51d458d2b17c7ebf1a299ce91914951e9c1fce36dc4bd28a90deeeec84f75a447b7521982e6657581ed4b4742eb9c5f49d57d712d586db879dcbcc0d6ca594c74dca9771ee899380c62d76351d0b04bbde6f703723c568f7b8ccfe66eb7c597eeabc1b0a3c7d33d920da0381288ab9921a7b70784829ce04ce4f0bd25998da97ef758a6da2e46'
      ]
  >>> print repr(pyssss.recoversecret(shares))
  'hun\x00ter2'

  """

    global _padchar

    output = StringIO.StringIO()
    PySSSS.decode([StringIO.StringIO(shares[i].decode("hex")) for i in xrange(len(shares))], output)
    secret = output.getvalue()
    output.close()

    try:
        crc, padnum, secret = int(secret[0:8], 16), int(secret[8:12], 16), secret[12:]
        secret = secret[padnum:]
        if (binascii.crc32(secret) & 0xFFFFFFFF) != crc:
            raise ValueError
    except ValueError:
        raise ValueError("could not reconstruct a valid secret. do you have enough data?")

    return secret
Ejemplo n.º 5
0
 def test_not_a_share(self):
     with self.assertRaises(ValueError):
         PySSSS.splitsecret(_secret, 1, 1)
Ejemplo n.º 6
0
 def rand_shares(self, secret, maxshares):
     numshares = random.randrange(3, maxshares)
     threshold = random.randrange(2, numshares)
     shares = PySSSS.splitsecret(secret, threshold, numshares)
     return (shares, threshold)
Ejemplo n.º 7
0
 def test_bad_threshold(self):
     with self.assertRaises(ValueError):
         PySSSS.splitsecret(_secret, _numshares, _threshold)
Ejemplo n.º 8
0
 def test_not_enough_shares(self):
     secret = str(os.urandom(100))
     (shares, threshold) = self.rand_shares(secret, 8)
     with self.assertRaises(ValueError):
         PySSSS.recoversecret(random.sample(shares, threshold-1))
Ejemplo n.º 9
0
 def test_roundtrip_unpadded(self):
     secret = str(os.urandom(1024))
     (shares, threshold) = self.rand_shares(secret, 8)
     recovered = PySSSS.recoversecret(random.sample(shares, threshold))
     self.assertEqual(recovered, secret)
Ejemplo n.º 10
0
 def test_recoversecret(self):
     self.assertEqual(PySSSS.recoversecret(_goodsplit), _secret)
     self.assertNotEqual(PySSSS.recoversecret(_badsplit), _secret)
Ejemplo n.º 11
0
 def test_splitsecret(self, RangeMock):
     RangeMock.side_effect = self.seq_random
     shares = PySSSS.splitsecret(_secret, _threshold, _numshares)
     self.assertEqual(shares, _goodsplit)
     self.assertNotEqual(shares, _badsplit)