A password-based implementation of threshold encryption
C Shell
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.gitignore
COPYING
Makefile
Makefile.am
README
build.sh
common.h
crypt.c
crypt.h
file.c
file.h
hkdf.c
hkdf.h
hkdf_test.c
hkdf_test.h
main.c
main.h
shares.c
shares.h
ui.c
ui.h
util.c
util.h

README

DESCRIPTION

threshcrypt - A password-based implementation of threshold encryption

LICENSE

Simplified BSD License.  See the included 'COPYING' file.

INSTALL

Just run 'make' and copy the binary somewhere.  You can also run 'make static'
to build a staticly linked version, which will be compressed with UPX if it is
installed in your $PATH.  Tested on x86_64 & i386 Linux with gcc and glibc. t

USAGE

Encrypt:
threshcrypt -t threshold -n shares input_file [output_file]

Decrypt:
threshcrypt input_file [output_file]

See main.c for other options until I update this file.

NOTES

* This is *ALPHA* software. No attempt will be made to maintain file format
  backwards compatibility until a beta relase.

* Currently, no automatic adjustment is done to the work factor of the KDF
  to compensate for the number of encrypted shares it needs to be run against.
  With a large number of shares the default parameters will be rather slow to
  verify a share password.

    CRYPTO DESIGN

    Operation overview:

    When encrypting, first the user is prompted to enter passwords for each
    share.  As each password is confirmed, it is fed to PBKDF2 along with a
    random 12 byte salt in order to generate a 'share key'.  As soon as the
    share key has been generated, the password is zeroed in memory.

    Once all the share keys have been generated, a random master key is
    generated, using the share keys as an additional entropy source (this
    helps if your RNG/PRNG is poor quality).  The master key is then
    MAC'd and split into a series of shares using Shamir's secret sharing.
    Each share is encrypted with the corresponding share key and then zeroed
    in memory.

    Finally, the plaintext is read in chunks which are then encrypted and MAC'd
    to prevent the data from being read/tampered with.


    For decryption, the user is prompted to enter 'any password' with an
    indication of how many shares have been unlocked and how many are needed
    to recover the master key.  For each password, *all* shares are checked in
    turn and a running total how how many more shares have been been unlocked
    is kept (multiple shares can have the same password).  Once enough shares
    have been decrypted, the master key is recovered.  The master key is then
    tested against the checksum.  If the master key looks good, then the
    ciphertext chunks will be verified and decrypted.



    Other notes:

    The chunked file data is stored using CTR+HMAC encrypt-then-mac.
    I may later add options to GCM / EAX / other authenticated encryption
    modes, but it's not worth the trouble right now.  Simmilarly, currently the
    only supported ciphers and hashes are AES and SHA-256 respectively.

    I (ab)use PBKDF2 a bit as a key expansion function.  This is because if you
    specify a larger than hashlen for PBKDF2's output size and use that key
    material for anything other than a single large key it can be attacked
    in parallel.  I'd rather use the HKDF expansion function to generate the
    subkeys, but I didn't find a library and didn't want to screw it up^W^W^W
    implement it myself.

    I *ALSO* (ab)use PBKDF2 with a small number of iterations as a replacement
    for HMAC to verify the master key.  Plain HMAC would probably be fine for
    that, but I'm paranoid and this is how LUKS does master key verification.
    This scheme will hopefully add some additional protection in case the hash
    algorithm used is broken.

TODO

* add support for other KDFs besides pbkdf2, starting with scrypt
* implement locked_malloc/unlock_free and use it for libgfshare and libtomcrypt
  structs
  - should page align and round up size to whole pages to ensure freeing has no
    side effects
* copy code from crypt_data to ctr_hmac_block which will take a ctr sturct as
  an argument.
  - wrap with ctr_hmac_dec_block and ctr_hmac_enc_block macros
  - convert crypt_data to a wrapper for the above
* implement ctr_hmac_fd wrapped by ctr_hmac_dec_fd and ctr_hmac_enc_fd
* mlock sensitive memory regions in libgfshare and libtomcrypt before using them
* do user interaction on /dev/tty so that data can be accepted on stdin