Skip to content

Threefish & Skein complete implementation - 256, 512 and 1024 bits.

Notifications You must be signed in to change notification settings

strlcat/tfcipher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Threefish & Skein complete implementation - 256, 512 and 1024 bits.

WHAT IT IS

This is basic, but fast and conforming implementation of Threefish
block cipher and Skein hash function, with variable size output.

It supports all bit widths that are defined by Threefish: 256, 512 and 1024 bits.

It is endian independent, this means that it can work on both big and little
endian machines equally.

The implementation also includes code for operating Threefish in CTR, ECB, CBC and XTS
modes of operation, as well as OFB like STREAM mode API which turns it into stream cipher.
There is also Threefish based PRNG, CTR modes API to ease adjusting counter and some test programs.

WHAT IT IS NOT

It is not an encryption program, application or cryptographic library like OpenSSL.
If you need one, take a look at the author's tfcrypt project
(look at one which has this implementation as it's base).

DESIGN GOALS

Unlike my previous "tf1024" implementation of Skein and Threefish, this one seeks for these goals:

- Implement the whole set of bit widths: 256, 512 and 1024 bits,
- Make the code alot easier to read: group same operations with macros, and format it nicely,
- Care about portability (although tf1024 had it done right too),
- Split the implementation into separate TUs, so that only necessary things maybe taken into
  the project that needs a Threefish and/or Skein implementation,
- Allow for easy extension if needed (more modes of operations for example),
- A very easy test place to try out new symmetric cryptography ideas.

I think I achieved all goals I objected.

OVERVIEW

tfdef.h, tfcore.h, tfenc.c, tfdec.c:
	Threefish core files which implement Threefish
	cipher itself in it's three bit width versions: 256, 512 and 1024 bits.

skein.h, skein.c:
	Skein hash function core files which implement Skein ontop of Threefish.

tfblk.c:
	Single block endian independent encryption routines.

tfctr.c:
	Counter (CTR) mode for Threefish, capable of encrypting an arbitrary length message.

tfctrapi.c:
	Counter adjustment for CTR and CTR capable modes of operation.

tftweakapi.c:
	Tweak adjustment in a portable way (no direct key words manipulation).

tfecb.c:
	ECB mode of operation.

tfcbc.c:
	CBC mode of operation.

tfxts.c:
	XTS (XEX with cipher text stealing) mode of operation, which is adjusted to
	256, 512 and 1024 bits block size (see IRR_POLY_CONST define).
	This implementation takes two keys: one encryption key and one XTS key.

tfe.h, tfe.c:
	TFE is a Threefish keystream generator. While CTR mode turns block cipher
	into stream cipher already, it is not adapted in the way to generate a truly
	"ondemand mode" stream, i.e., if you request bytes not round to block size.
	This API is specially designed that to provide a truly "stream" experience.

	For example, requesting from it 167, 76 and 89 bytes, then resetting it and
	starting over with same settings, then requesting 121, 101 and then 110 bytes
	again will yield the same 332 bytes of keystream which is to be XORed with your plaintext.

	To use it with same key you should provide an IV of Threefish block size length.
	Without providing an IV, a zero IV is used. You should already know that reusing
	same key and IV for two different messages will compromise their contents because
	XOR of them will yield the clear, not encrypted difference between two.

tfprng.h, tfprng.c:
	Threefish Pseudo Random Number Generator which works ontop of TFE described above.
	There are functions to seed it from single 64 bit integer seed or from keyed seed
	which is equal to Threefish key size. The Threefish is considered strong enough
	so there are functions to generate random integers as well as to generate random buffers
	of arbitrary length. TFE as an engine guarantees that no random bit is lost.

tfstream.c:
	An OFB mode of operation, which uses TFE as it's backend. The XOR is done by using
	machine word size for speed improvement. It accepts TFE context as it's argument.

tfblktst.c:
	A test program to see the avalanche effect of Threefish as well as to see that
	it works correctly (encrypts and decrypts the plaintext with a key).
	It accepts arguments: argv[1] is a key which is copied directly into a key buffer,
	argv[2] is a plaintext to be encrypted, and argv[3] is a decryption key for a
	different (or not) key test.

tfcrypt.c:
	A minimum test program which encrypts a file using XTS mode. The sector size for
	XTS mode is set to 512 bytes, so it could be slower than, for example, CTR mode.
	With -e/-d argument it reads key as is, from file, as a "raw" key, while with
	-we/-wd argument it hashes an arbitrary long key data into a Skein hash, which
	is then used as a key. No attempts are made to further harden this hash however.
	You should use this program only to test Threefish and Skein.

tfecrypt.c:
	A version of tfcrypt.c above which uses TFE and tfstream as it's backend. It always
	hashes key data using Skein unlike tfcrypt.c, which offers loading a "raw" key.

skeinhash.c:
	A Skein hash program. Reads the file and hashes it. Optional -b argument may specify
	resulting hash bit width, but no more than maximum block size bit width.

tfrand.c:
	Generates random data using CTR mode of operation. For initial seed it reads
	random data from /dev/urandom file. An optional argument specifies the number of
	bytes to be generated (accepts single multiplication prefixes, for example, "12M"
	for "12 megabytes").

tferand.c:
	Generates random data using TFE engine. As tfrand.c, uses /dev/urandom for initial seed.
	Accepts similar argument to limit it's output size.

tftest.c:
	An encryption and decryption speed test program.

tfetest.c:
	Version of tftest.c for TFE engine.

genrconst.c:
	A program to generate random Threefish round constants. Uses /dev/random as the initial
	seed source, and current PRNG to generate random integers within the given range.

tfsupport.h, mhexdump.c, numconv.c, xstrlcpy.c:
	Support routines for formatted hex dumps, safe string copy, and human to numeric conversions.

API OVERVIEW

The main Threefish API and Modes API are organised in the "decomposed" way: the key, data blocks
and counters/IVs are separate arguments, not unified into a "context" structure. Because Threefish
does not precompute key (the key is accepted as is into cipher), there is no key conversion
function into something that cannot be directly seen by user. It's easier and more obvious.

The exceptions are those where using separate data fields is inappropriate or not convenient:
Skein needs it's context structure to efficiently operate over multiple data blocks and not
to load and store arguments to it's functions, so the TFE too. PRNG uses opaque data structure
which user must allocate somewhere by querying for size first.

There is no function to set the key. All keys are supplied as is. The tf_convkey() is currently
to correct the endianness of key to be portable between various machines.

Include tfdef.h to get the main encryption/decryption function prototypes, the Modes prototypes,
and the endian independent single block function prototypes. This header file also defines useful
macros and values to make your programs portable between various Threefish bit widths.

Include skein.h to get Skein hash function main prototypes (init/update/final), as well as
Skein context internals.

Include tfe.h to get TFE related functions and definitions, and to work with TFE.

Include tfprng.h to get PRNG function prototypes and definitions.

Do not use tfsupport.h and tfcore.h. While tfcore.h is required for the Threefish code to
build and run with your application, tfsupport.h and related code is unnecessary.
tfcore.h defines Threefish internal mechanics, and should never be used by
programs intended to be portable.

The function names, macros and variable names are self explanatory.
It should not be hard to get what they mean. The complete documentation is soon to be written.

THREEFISH NOTES

This implementation does not take into view that Threefish is a tweakable block cipher.
It eliminates this property from it, turning it into an ordinary block cipher like AES, Twofish etc.
The fact that XTS is tweakable block cipher mode of operation (although somewhat limited),
was the primary reason to strip off this property from Threefish itself. Another one is the fact
that the key size maybe safely extended from tweak as well as Threefish tweak is a part of key.

By turning tweak into key you get spare key bits: +256 bits, turning into TF256/512, TF512/768 and
TF1024/1280, although not all of them are really key bits - they are summed internally.

This implementation leaves the choice up to you to use tweak or not: for TF256, the key layout is:
K1 K2 K3 K4 K5 T0 T1 T2. Here, K5 T0 T1 T2 is a key extension.
The TF_TWEAK_WORD1, TF_TWEAK_WORD2 and TF_TWEAK_WORD3 defines will point you at any time
to the T0, T1 and T2 words inside key. K5 here is a XOR sum of K1-K4 in original
Threefish plus THREEFISH_CONST. It is also used this way by Skein.

Functions in tftweakapi.c will aid you in setting and adjusting tweak for your own modes.
You should use them instead of direct tweak word manipulation, as they also take care about
setting it per official specification, and they do endianness conversion.

SKEIN NOTES

Skein MAC mode is not implemented here. Unlike my old "tf1024" implementation, this one just
copies your key into Skein context without preprocessing.
I believe it has is the same security, although resulting hashes will be different.
To get the key for lengthy input, you should pass it through the unkeyed Skein.

If you never used MAC feature of Skein, then you should get same hashes.
This Skein successfully passes it's test vectors from the original skein1.3.pdf paper.

The length of input MAC key is not +256 bits, but a length of the TF block. Skein uses
tweak feature of Threefish, and sets K5 (K9, K16) to the XOR of all previous
key words and THREEFISH_CONST. It is useless to fill the key extension with the user data,
just to waste it then completely (Skein just overwrites these key words).

GENERAL SKEIN 1.3 COMPATIBILITY NOTE

This library does NOT give any warranty to be _fully_ compatible with anything Skein 1.3 (or any other version) documentation
requires for a reference Skein implementation. This code is just a result of my personal adaptation of (IMHO) ugly and quite
obscured reference C implementation for my "tfcrypt" encryption program.
Deviations from reference implementations are listed above, please, do NOT expect more than plain,
unkeyed hashing and plain keyed encrypting. Test vectors are also not implemented (yet).

AUTHOR

Andrey Rys <rys@lynxlynx.ru>, 2021.

LICENSE

This implementation of Threefish and Skein is, just like Threefish itself is put into public domain.
Anyone can use and adapt this code to his own needs and modify it as he needs.
There are no restrictions to use this code: you may use it freely for any purposes, both
inside commercial and open source software.

The supplying code (xstrlcpy.c, mhexdump.c, numconv.c) is my creation, hereby I place them
into public domain too along with this code.

About

Threefish & Skein complete implementation - 256, 512 and 1024 bits.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published