This is a first prototype draft of the stream cipher "zxp-Enigma". It is meant as a manually processed stream cipher, but still simple to handle. Prerequisites: -------------- - several 26 letter English alphabet Scrabble or Bananagram tiles (A-Z) - a ruler as large as one complete alphabet - an item as counter, a penny for instance - a bag for shaking the tiles - a Vigenere table (Tabula Recta) of the 26 letter English alphabet - pen and paper (optional) Actually it is based on the same technique as with my previous approach named "zxp". Basically it consist of two mixed up 26 letter alphabets lined up in two rows, one above the other which get scrambled and mixed constantly. From such an "internal state" we calculate the keystream. In this prototype draft I am only describing the PRGA (Pseudo Random Generation Algorithm). The KSA (Key Schedule Algorithm) will follow soon. In fact the PRGA is needed first as it is an essential part of the KSA. A first very simplistic example implementation in HTML/JavaScript is available here http://www.freecx.co.uk/crypto/zxp/zxp-Enigma_v20181026.html If you prefer you can download the file and run it locally. These are the checksums of zxp-Enigma_v20181026.html MD5 0d7ef36eb5d0e3688e0f3a9e06036803 SHA1 0479890fa59ab9819dc72c9af7033a985c715a52 SHA256 6a578f4796e57de6e640c143c40e843f600f12e930c91d5fad384adb3c81e061 Assuming that we have injected the key material via the KSA into the internal state, we would end up with a permutation of two mixed and scrambled alphabets having 52 items like below. #) initial permutation +-----------------------------------------------------+ | J V I O T E T S E G O N M P Y V Q M W X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X U B P F B A H | +-----------------------------------------------------+ * = counter incremented by 1 modulo 26 The constant mix-up of the internal state consists of three different steps - character swapping - counter increasing - mixed alphabet rotation To perform this in a synchronised fashion both communication partner have agreed upfront on a secret keyword/phrase and at least two swapping index characters and one keystream calculation index character. We omit the secret keyword/phrase right now, because it is only used with the KSA - which is not part of this draft. In this example the two swapping index characters would be Z and X and the keystream calculation index character M This combination will be used for the generation of the complete keystream. Back to the initial permutation on which we will apply the character swapping first. Search for both swapping index characters Z and set two markings +-----------------------------------------------------+ | J V I O T E T S E G O N M P Y V Q M W X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X U B P F B A H | +-----------------------------------------------------+ | | Swap the opposite letters I O +-----------------------------------------------------+ | J V T E T S E G O N M P Y V Q M W X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X U B P F B A H | +-----------------------------------------------------+ | | +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M W X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X U B P F B A H | +-----------------------------------------------------+ | | Search for both swapping index characters X and set two markings | +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M W X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X U B P F B A H | +-----------------------------------------------------+ | Swap the opposite letters W | +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X B P F B A H | +-----------------------------------------------------+ | U | +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X W B P F B A H | +-----------------------------------------------------+ | After the swapping we calculate or keystream character. Search for both keystream calculation index characters M and set two markings | | +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J U L N R C Q X W B P F B A H | +-----------------------------------------------------+ Swap the opposite letters | | +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J L N R C X W B P F B A H | +-----------------------------------------------------+ Q + U Add the opposite letters mod26 or via a tabula recta Q + U = K Search for first occurrence of K from top left to the right and set a marker - if K is not in the top row, start searching the bottom row from left to right. +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ | The opposite letter is the keystream character T +-----------------------------------------------------+ | J V O I T E S E G O N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ | Search for the position of K to the right until you find the next K and set a marking. +-----------------------------------------------------+ | J V O I T E T S E G O N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ | Swap the opposite letter with the one above the incremental counter. In fact we *only* swap letters in the *top* row based on the incremental counter position. J O +-----------------------------------------------------+ | V O I T E T S E G N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ | +-----------------------------------------------------+ | O V O I T E T S E G J N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ | Increase the counter by 1 - if it reaches over the far right end after increasing place it a the leftmost position again. (counter +1) mod26 +-----------------------------------------------------+ | O V O I T E T S E G J N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ The next step is the rotation of both rows +-----------------------------------------------------+ | O V O I T E T S E G J N M P Y V Q M U X L R D C I W | +-----------------------------------------------------+ * +-----------------------------------------------------+ | Y A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ W +-----------------------------------------------------+ | O V O I T E T S E G J N M P Y V Q M U X L R D C I | +-----------------------------------------------------+ * +-----------------------------------------------------+ | A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ Y W +-----------------------------------------------------+ | O V O I T E T S E G J N M P Y V Q M U X L R D C I | +-----------------------------------------------------+ * +-----------------------------------------------------+ | A Z Z G S K D F H K J Q L N R C U X W B P F B A H | +-----------------------------------------------------+ Y +-----------------------------------------------------+ | Y O V O I T E T S E G J N M P Y V Q M U X L R D C I | +-----------------------------------------------------+ * +-----------------------------------------------------+ | A Z Z G S K D F H K J Q L N R C U X W B P F B A H W | +-----------------------------------------------------+ ... and so one ... Some remarks on special constellations: ======================================= In case both swap letters are opposite each other, like in the example below | +-----------------------------------------------------+ | Y O Z O I T E T S E G J N M P Y V Q M U X L R D C I | +-----------------------------------------------------+ * +-----------------------------------------------------+ | A V Z G S K D F H K J Q L N R C U X W B P F B A H W | +-----------------------------------------------------+ | no swap will be performed. In case both keystream calculation index character are opposite each other, like in the example below + | +-----------------------------------------------------+ | Y O Z O I T E T S E G J N W P Q V Q M U X L R D C I | +-----------------------------------------------------+ * +-----------------------------------------------------+ | V Z G S K D F H K J Y L N R C U X M B P F B A H W | +-----------------------------------------------------+ A | we add M + M = Y and A will become the keystream letter. + | +-----------------------------------------------------+ | J O Z O I T E T S E G Y N W P Q V Q M U X L R D C I | +-----------------------------------------------------+ * +-----------------------------------------------------+ | A V Z G S K D F H K J Y L N R C U X M B P F B A H W | +-----------------------------------------------------+ | we add M + M = Y and Y will become the keystream letter. In case the second keystream search character Y is in the same column as the incremental counter - like in the example above - no swap will be performed. In general, if two letters that are intended to swap position are equal, no swap will be performed. These situations are "dead" swaps, because the characters can’t change places. But the next rotation will shift the "dead" swap away. That’s one of the reasons why I’ve implemented the rotation. Of course sender and receiver can agree upfront on several different combinations of swapping index and keystream calculation index characters, like for instance ZXM CTB HQL In addition they need to agree also on a related counter for each combination that, when it has been reach after the desired amount of keystream letters, indicate that the next combination is to be used. For example: ZXM 13 - CTB 23 - HQL 17 This means we use ZXM for the first consecutive 13 keystream letters, then switch to CTB for the next 23 and finally to HQL for the upcoming 17 letters. If the keystream is longer the the sum of all related counter (13+23+17) we roll over to ZXM again, performing as described above. We use these combinations in a looping fashion. Some remarks on the design rational: ==================================== The algorithm is build explicitly of two mixed-up 26 letter alphabets and four swapping indices. This way, in combination with the row rotation, we are able to maintain a proper character swapping, mixing and a relatively fast permutation shuffle. Additionally these four swapping indices ensure that over time every character get swapped. You may have noticed that the letter swapped based on the incremental counter will follow up the counter position by the next rotation. This way it will be swapped away in the upcoming swapping and calculation procedure to a probably unknown location. The reason for the keystream calculation index character is that we never use a fixed position from where to draw the keystream character but instead keep it somehow more unpredictable. The mentioned HTML/JavaScript implementation offer tests on the generated keystream like Chi-squared Durbin-Watson statistic Shannon's entropy Chars per run Index of coincidence Dependence Chi-squared of consecutive letters Letter frequency chart N-Gram statistics with variable N-Gram size First test showing some quite good results. =========================================== Initial State JVIOTETSEGONMPYVQMWXLRDCIWYAZZGSKDFHKJULNRCQXUBPFBAH Secret key swap selection ZXM Keystream length 600 Tests applied to the letter output with number of characters: 600 Chi-squared (less than 34.4 is good) = 18.539 Durbin-Watson statistic (should be close to 2.0) = 1.9509 Shannon's entropy (should approach 4.7) = 4.6791 Chars per run (should be close to 2.0) = 2.0066 Index of coincidence (as low as 0.03846 for random, around 0.066 for English text) = 0.0380 Dependence Chi-squared of consecutive letters (less than 671 is good) = 626.44 Letter frequency chart A = 22 | #####################################--------------------------------------------------------------- B = 17 | #############################----------------------------------------------------------------------- C = 19 | ################################-------------------------------------------------------------------- D = 20 | ##################################------------------------------------------------------------------ E = 21 | ####################################---------------------------------------------------------------- F = 23 | #######################################------------------------------------------------------------- G = 29 | #################################################--------------------------------------------------- H = 20 | ##################################------------------------------------------------------------------ I = 26 | ############################################-------------------------------------------------------- J = 34 | #########################################################------------------------------------------- K = 20 | ##################################------------------------------------------------------------------ L = 27 | #############################################------------------------------------------------------- M = 27 | #############################################------------------------------------------------------- N = 20 | ##################################------------------------------------------------------------------ O = 25 | ##########################################---------------------------------------------------------- P = 21 | ####################################---------------------------------------------------------------- Q = 24 | ########################################------------------------------------------------------------ R = 23 | #######################################------------------------------------------------------------- S = 19 | ################################-------------------------------------------------------------------- T = 22 | #####################################--------------------------------------------------------------- U = 32 | ######################################################---------------------------------------------- V = 18 | ##############################---------------------------------------------------------------------- W = 23 | #######################################------------------------------------------------------------- X = 24 | ########################################------------------------------------------------------------ Y = 23 | #######################################------------------------------------------------------------- Z = 21 | ####################################---------------------------------------------------------------- N-Gram statistics - first 30 results 1 TJ 4 0.67% 2 JF 4 0.67% 3 GE 4 0.67% 4 HA 4 0.67% 5 XG 4 0.67% 6 UC 4 0.67% 7 UM 4 0.67% 8 TT 3 0.5% 9 TY 3 0.5% 10 QF 3 0.5% 11 QO 3 0.5% 12 AU 3 0.5% 13 NM 3 0.5% 14 FY 3 0.5% 15 GG 3 0.5% 16 GI 3 0.5% 17 SA 3 0.5% 18 XJ 3 0.5% 19 BJ 3 0.5% 20 UQ 3 0.5% 21 UU 3 0.5% 22 UV 3 0.5% 23 PB 3 0.5% 24 VG 3 0.5% 25 LS 3 0.5% 26 LV 3 0.5% 27 LL 3 0.5% 28 ZN 3 0.5% 29 ZX 3 0.5% 30 DP 3 0.5% Even these ordered alphabets below as initial state produce good results ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ Perhaps someone around here is able to figure out a weakness or some kind of clever attack. Finally I like to remember that this algorithm has a relative tiny internal state, so please don't use it for encryption of your valuable secrets ;-)