0

I am trying to use SSS to encrypt my private keys, using a modified version of the example code shown in the docs.

# encrypt.py
from binascii import hexlify
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Protocol.SecretSharing import Shamir
import os
import shutil

key = get_random_bytes(16)
n_splits = 5
k_splits = 5
shares = Shamir.split(k_splits, n_splits, key)

shares_folder = "shares"

if os.path.isdir(shares_folder):
    shutil.rmtree(shares_folder)

os.mkdir(shares_folder)

for idx, share in shares:
    with open(os.path.join(shares_folder, "share_{}.txt".format(idx)), "wb") as fp:    
        fp.write(bytes((str(idx) + ","), encoding="utf-8"))
        fp.write(hexlify(share))

with open("clear.txt", "rb") as fi, open("enc.txt", "wb") as fo:
    nonce, tag = [ fi.read(16) for x in range(2) ]
    cipher = AES.new(key, AES.MODE_EAX)
    ct, tag = cipher.encrypt(fi.read()), cipher.digest()

    fo.write(nonce + tag + ct)

# decrypt.py

from binascii import unhexlify
from Crypto.Cipher import AES
from Crypto.Protocol.SecretSharing import Shamir
import sys
import os

shares_folder = "shares"
shares = []

for filename in os.listdir(shares_folder):
    with open(os.path.join(shares_folder, filename), "r") as shares_fp:
        lines = shares_fp.readlines()
        for line in lines:
            idx, share = line.split(",")
            shares.append( (int(idx), unhexlify(share)) )

key = Shamir.combine(shares)

with open("enc.txt", "rb") as fi:
    nonce, tag = [ fi.read(16) for x in range(2) ]
    cipher = AES.new(key, AES.MODE_EAX, nonce)
    try:
        result = cipher.decrypt(fi.read())
        cipher.verify(tag)
        with open("clear2.txt", "w") as fo:
            fo.write(str(result))
    except ValueError:
        print ("The shares were incorrect")

The expectation is that each key share will be written into a text file within the shares folder. During decryption, the key shares are combined and used to decrypt the secret.

However, I got the following output.

# encrypt output

share:  b'EB\x0b\xb1\xf8%\xc6W;\x16oE{\xcb\x84\xe0'
hexlify:  45420bb1f825c6573b166f457bcb84e0
share:  b'A\x1d$\x9af\x8a\x8b"O\xa2\xe9D\x8b\x8f\x92\xd0'
hexlify:  411d249a668a8b224fa2e9448b8f92d0
share:  b',\xd1!\x06\xc6An\x90u\xb1\xbe\x1d\x1bC\xd1\xb0'
hexlify:  2cd12106c6416e9075b1be1d1b43d1b0
share:  b"\xb7'\xe0O\xc3@Z\xddR\xbf\x80f\xa6*\x020"
hexlify:  b727e04fc3405add52bf8066a62a0230
share:  b'\xc1RSAb\xc0\x18\x87\xfc\xb2\xf0\x19Ng;>'
hexlify:  c152534162c01887fcb2f0194e673b3e

Key:  b'@\x06_p5-\xc2\xc6]\x01\xef\xcbN\x87\xb9\xa3'

# decrypt output
share:  45420bb1f825c6573b166f457bcb84e0
unhexlify:  b'EB\x0b\xb1\xf8%\xc6W;\x16oE{\xcb\x84\xe0'
share:  411d249a668a8b224fa2e9448b8f92d0
unhexlify:  b'A\x1d$\x9af\x8a\x8b"O\xa2\xe9D\x8b\x8f\x92\xd0'
share:  2cd12106c6416e9075b1be1d1b43d1b0
unhexlify:  b',\xd1!\x06\xc6An\x90u\xb1\xbe\x1d\x1bC\xd1\xb0'
share:  b727e04fc3405add52bf8066a62a0230
unhexlify:  b"\xb7'\xe0O\xc3@Z\xddR\xbf\x80f\xa6*\x020"
share:  c152534162c01887fcb2f0194e673b3e
unhexlify:  b'\xc1RSAb\xc0\x18\x87\xfc\xb2\xf0\x19Ng;>'
Shamir decryption key:  b'@\x06_p5-\xc2\xc6]\x01\xef\xcbN\x87\xb9\xa3'

The shares were incorrect

Even though the key and shares are identical, I still got the incorrect secret. What is going on here?

disguisedtoast
  • 149
  • 1
  • 4
  • 15
  • In the encryptor, this line `nonce, tag = [ fi.read(16) for x in range(2) ]` doesn't make any sense. It looks like that belongs in the decryption program, not the encryption program. I would expect that `clear.txt` contains only plaintext. – President James K. Polk Aug 17 '22 at 18:32
  • Interesting. However, the official docs showed wrote the nonce + tag + ct to the output file, even though nonce is not defined. I tried removing nonce from the file write, but the shares still could not reconstruct the secret. – disguisedtoast Aug 18 '22 at 03:45
  • if you don't provide the nonce yourself, the library will create a random one for you each time you call new(). In either case, you must always write it out. – SquareRootOfTwentyThree Aug 18 '22 at 07:45
  • Which is what I did in encrypt.py. Is that not the correct method? – disguisedtoast Aug 18 '22 at 07:57
  • Look again more carefully at the code in encrypt.py. Where did you get the nonce from in that code? Not from the cipher object. You read it in from `clear.txt`, along with a tag, but presumably `clear.txt` does not contain a nonce or a tag. – President James K. Polk Aug 18 '22 at 12:24
  • 1
    Hi James K. Polk, looked through some other examples and realized that the cipher object has a nonce attribute. Thanks for pointing out my mistake. – disguisedtoast Aug 19 '22 at 01:43

0 Answers0