The Infinite Cipher is a family of arbitrarily high strength ciphers, ranging from an everyday performance balanced 65536 bits to whatever number you can think of (as long as it is a power of 2 and your computer has sufficient memory).
Due to relying on the Algorithm Enhancement Stuff found in modern processors the Infinite Cipher easily deliver speeds competitive with popular implementations of lesser ciphers. Furthermore the built-in authentication is good for both speed and ease of use.
The Infinite Cipher has been a favourite amongst many users of homemade headgear since its release on April 1st 2025.
In addition to this specification it is recommended to read the infinite512.c implementation file.
Each member of the cipher family is identified by two numbers, a strength level s, and a tag size t. s must be at least 16, and t must be at least 9 and lower than s. The nominal strength of the cipher is 2^s bits, and the size of the generated authentication tag is 2^t bits. The security claim of 2^s bits assume that an attacker has access to no more than 2^(16*s) known or chosen plaintext blocks.
While infinitely many members of the Infinite Cipher family are defined, an implementation may choose to only implement a finite number of them.
The core of an Infinite Cipher member is the Scramble function, it takes a buffer (the Base) of size 2^(s-2) bytes and permutes it in a chaotic fashion, it also takes as input a Tweak number that used in the permutation. The Base is conceptually divided into 128 bit words, all operations are performed on chunks of 4 words aka 512 bit superwords, conveniently equivalent to AVX512 registers. A few constants are generated based on s:
Round count r = floor(s^2 / 8)
Round length l = 4 * roundToOdd(φ^-2 * 2^(s-10))
Fetch offset o = 4.5*l + 2^(s-7) + 18
The first 11 superwords of the Base are moved to a separate buffer called the State, and are referred to as state0 through state10. Three pointers into the Base are tracked:
Store pointer, initially points to word 0 of the Base.
Load pointer, initially points to word 44 of the Base.
Fetch pointer.
The pointers are moved throughout the computation, the Base is considered to wrap around, so whenever a pointer would point outside the Base it should be moved to the equivalent location. Conceptually the Store and Load pointers delimit the hole left when the State was moved, this conceptual hole will remain throughout the computation, but move along with the pointers.
The follow operations are used in the computation:
XOR - The bitwise exclusive or is performed on two superwords, returning a new superword.
ADD - Two superwords are each considered as 16 little endian 32 bit numbers, they are added together pairwise with two's complement overflow, producing 16 new numbers that form a new superword.
AES - A superword is considered as four 128 bit words, each word is transformed by applying a single AES encryption round, without the AddRoundKey step.
r rounds run as follows:
- The Store and Load pointers start each round at the value they had at the end of the previous round.
- The Fetch pointer is set to be
owords ahead of the Store pointer. - The lower 128 bit word of
state0isXORed with the lower 128 bits of theTweakin little endian. - Similarly the following three words of
state0areXORed with the lower 128 bits ofTweak+1,Tweak+2andTweak+3respectively. IfTweak+3is too large to fit in a 128 bit value then the overflowing bits areXORed intostate1, thenstate2etc. If 1408 bits isn't enough continue with superwords from theBase, starting at the Load pointer. (While there is no definite limit to how large theTweakvalue may get, practical implementations can generally compute a bound that will not be reached before running out of address space.) - Then
lsteps run as follow:- Superword
ldis loaded from the load pointer. - Superword
stis produced byADDingldtostate3. - Superword
ftis loaded from the fetch pointer. stis stored to the store pointer.ldisXORed intostate0.state0isAESed.state3isXORed intostate0.stisXORed intostate1.state1isAESed.ftisXORed intostate1.state3isADDed tostate2.ldandstare each moved 4 words forward.ftis moved 5 words backwards.- The
Stateis rotated 3 superwords backwards, sostate0becomesstate8,state1becomesstate9,state2becomesstate10,state3becomesstate0etc.
- Superword
All Infinite Cipher members accept an arbitrary length key, the key is transformed into a fixed length Lid. First a buffer of length 2^(s-2) bytes is zeroed, then for each 2^(s-2) bytes of the key those bytes are XORed into the buffer, and the buffer is Scrambled with Tweak 1+4*blockId, where blockId is 0 for the first key block, 1 for the following etc. The final block is padded with zeroes at the end, and the final Tweak is 1+4*blockId+4*blockLength. If the key length is zero it is treated as one length 0 block, otherwise there will never be a length 0 block. The final state of the buffer is the Lid.
The encryption procedure requires a nonce, the nonce must be no longer than 2^(s-2) bytes, and must be unique for each message. A Mask buffer of length 2^(s-2) bytes is created by XORing the Lid with the zero padded nonce and Scrambling the result using Tweak 3+4*nonceLength. A Tag buffer of size 2^(t-3) bytes is zeroed.
The plaintext is divided into blocks of length 2^(s-2) bytes. For each block the cyphertext is generated by XORing the plaintext block with the Mask and the Lid. The Mask is then updated by XORing it with the plaintext block and Scrambling it with Tweak 2*blockId, where blockId is 0 for the first block, 1 for the next etc. Then the Tag buffer is XORed with the first 2^(t-3) bytes of the resulting Mask buffer. The final block is zero padded and the Tweak value is 2*blockId+2*blockLength. The final ciphertext block is cropped to the length of the plaintext block. Note that the final Mask buffer state is not used for encrypting the plaintext, but must still be generated in order to compute the Tag. If the plaintext is length zero, then zero blocks are processed and the Tag is set using the initial value of the Mask buffer.
Decryption is done almost the same way as encryption, except that the plaintext must be computed by XORing the cyphertext, the Lid and the Mask. Decryption must also generate a Tag, compare it to the provided Tag, and reject the message if they do not match.
This initial implementation of the Infinite Cipher is limited to a maximum strength level of 62, delivering a strength of 4611686018427387904 bits. While one could desire a higher level, this will require a greater than 64 bit memory system for realistic use. As such memory systems are virtually non-existent at the moment I have decided to focus my initial effort on 64 bit systems.
Exactly one of infinite512.c and infinite128.c must be included in a project. infinite512.c is generally faster, but requires AVX512. infinite128.c uses only 128 bit registers and will run on most modern X86 and high end Arm chips. infinite.h works as header for either implementation. test.c is as the name implies only for testing the implementation, it should not be included in any other project.
This implementation relies on a buffer structure object that is passed around as a void pointer. The size of the buffer structure depend on the chosen strength level, the INFINITE_BUFFERSTRUCTURESIZE(s) macro has been included for easily calculating this size. The buffer structure is initialised with an s and a t parameter, along with a key. The buffer structure can be passed to the encrypt and decrypt functions in order to encrypt and decrypt with that key. A buffer structure can after a single initialisation be used any number of times, but may only be used by a single thread at once.
Example compiler invocations for the test code:
gcc test.c infinite128.c -maes -O3
gcc test.c infinite128.c -maes -mavx -O3
gcc test.c infinite512.c -mavx512f -mvaes -O3