From: Christian Schneider <100542.2132@CompuServe.COM> Newsgroups: sci.crypt.research Subject: New 128-bit block cipher: Cobra Date: 13 Apr 1996 05:38:15 GMT This paper describes the Cobra encryption algorithm, designed by Christian Schneider. To download the Winword version of this paper and some flowcharts of Cobra, take a look at the "Cryptography Web Site" at http://ourworld.compuserve.com/homepages/c_schneider ======================================================================== Cobra Block Cipher designed by Christian Schneider Am Beethovenpark 23 D-50935 Koeln Germany Fax: 0221 / 4680821 E-mail: 100542.2132@compuserve.com Introduction: Cobra is a fast, secure, and variable block cipher. By variable I mean that I leave it open how many rounds it has (though I give some recommendations) and how long the block length is. But the standard Cobra variant: Cobra-(24,128) has a block length of 128 bit, a maximum key length of 1152 bit (that means it can be anything from 1 bit to 1152 bit), and it has 24 rounds. Description of Cobra-(24,128) Subkeys: Cobra uses a large array of subkeys, which must be precomputed from a secret user key before encryption/decryption takes place, but once they are precomputed they can be stored as long as they are needed for the encryption/decryption of a file (or of more files). Of course after the encryption/decryption is finished they must be discarded, because they are the secret key. (all entries are 32-bit values) P-Boxes: (Permutation) P1,1 P1,2 P1,3 P2,1 P2,2 P2,3 P3,1 P3,2 P3,3 . . . . . . P24,1 P24,2 P24,3 288 byte S-Boxes: (Substitution) S1,0 S1,1 S1,2 ... S1,255 S2,0 S2,1 S2,2 ... S2,255 S3,0 S3,1 S3,2 ... S3,255 S4,0 S4,1 S4,2 ... S4,255 + 4096 byte W-Boxes: (Whitening) W1,1 W1,2 W1,3 W1,4 W2,1 W2,2 W2,3 W2,4 + 32 byte = 4416 byte These subkey-arrays must be precomputed from the user key in a similar way as the Blowfish algorithm makes it key expansion: 1. Initialize first the P-Boxes, the S-Boxes, and then the W-Boxes with a fixed string. This string consists of the hexadecimal digits of (pi). Of course there is nothing special about (pi). So any random string would work too, but it must be fixed and the same for every implementation. 2. XOR all entries of P1 with the first (3*32) bits of the key (that means, that you first XOR P1,1 with the first 32 bits of the user key, then XOR P1,2 with the second 32 bits of the user key, then XOR P1,3 with the third 32 bits of the user key), then all entries of P2 with the second (3*32) bits of the key (that means, that you first XOR P2,1 with the fourth 32 bits of the user key, then XOR P2,2 with the fifth 32 bits of the user key, and then XOR P2,3 with the sixth 32 bits of the user key), and so on for all bits of the key (maximum 1152 key bits = up to P12). Repeatedly cycle through the key bits until all P-Boxes (up to P24) have been XORed with key bits. The reason for only using the user key up to P12 and then repeating it up to P24 is that this makes a better key avalanche effect. If the user key is shorter then 1152 bit then just start to repeat the key earlier when it becomes necessary. All in all this procedure just makes all P-Boxes dependent on the user key. 3. Encrypt the all-zero string with the Cobra algorithm, using the subkeys described in steps (1) and (2). 4. Replace P1,1 and P1,2 and P1,3 and P2,1 with the output of step (3). 5. Encrypt the output of step (3) using the Cobra algorithm with the modified subkeys. 6. Replace P2,2 and P2,3 and P3,1 and P3,2 with the output of step (5). 7. Continue the process, replacing all P-Boxes with the output of the continuously changing Cobra algorithm. Then execute step (2) again, but before XORing the 32-bit parts of the user key with the current P-Box entries, just right circular shift (>>>1) every 32-bit part of the user key one bit. This also makes a much better key avalanche effect. And after step (2) just continue and execute steps (3) to (6) again, before going on to step (8). 8. Continue the process as described in steps (3) to (6), replacing all P-Boxes, all S-Boxes, and all W-Boxes with the output of the continuously changing Cobra algorithm. In total 294 iterations are required to generate all required subkeys. Encryption: Cobra is a so-called "generalized Feistel-Network" which has (at least) four sub-blocks per encryption block. Another advantage of these generalized Feistel-Networks is that (at least) the encryption routine can be pipelined, which makes the (encryption) algorithm run faster. To encrypt the 128-bit data element, X: Divide X into four 32-bit sub-blocks: A,B,C,D A = A xor W1,1 B = B xor W1,2 C = C xor W1,3 D = D xor W1,4 For r = 1 to 24 A' = D B' = (A xor F(B;Pr,1))>>>1 C' = (B xor F(C;Pr,2))>>>1 D' = (C xor F(D;Pr,3))>>>1 A = A' B = B' C = C' D = D' Next r A = A xor W2,1 B = B xor W2,2 C = C xor W2,3 D = D xor W2,4 Finally recombine A,B,C,D to get the ciphertext. The first and last part are the "Whitening"-parts where the actual plaintext is XORed with some key material (the first W-Box), and in the last part the ciphertext is again XORed with some other key material (the second W-Box) to form the actual ciphertext. This can also be seen as an input transformation and an output transformation. The middle part is the actual encryption part, which is iterated 24 times. The term ">>>1" stands for a right circular shift of one bit. I've implemented it in Cobra in order to make Cobra more secure against differential cryptanalysis based on iterative characteristics, because when shifting the bits, the differentials are also shifted. And these bit-shifts make Cobra also a bit more secure against linear cryptanalysis, because the bit-positions of the XOR of some unknown intermediate subdata bits, which must be the same for some rounds for linear cryptanalysis are also shifted, so that one must use "bad" (normal) linear approximations instead of "good" (precalculated) ones. But of course aside from this Cobra is in real life completely secure against differential and linear crypt- analysis, because if implemented correctly, the S-Boxes (and also the P-Boxes and W-Boxes) of Cobra are secret, because they are derived from the secret user key, and differential and linear cryptanalysis only works with known and constant S-Boxes. Decryption: To decrypt the 128-bit data element, X: Divide X into four 32-bit sub-blocks: A,B,C,D A = A xor W2,1 B = B xor W2,2 C = C xor W2,3 D = D xor W2,4 For r = 24 to 1 D' = A C' = (D<<<1) xor F(D';Pr,3) B' = (C<<<1) xor F(C';Pr,2) A' = (B<<<1) xor F(B';Pr,1) A = A' B = B' C = C' D = D' Next r A = A xor W1,1 B = B xor W1,2 C = C xor W1,3 D = D xor W1,4 Finally recombine A,B,C,D to get the plaintext. This is just the inverse of the encryption routine. The term "<<<1" stands for a left circular shift of one bit. F-Function: The F-Function is as follows: Y = F(X;Pr,n): Z = X xor Pr,n (Key-dependent Permutation of the input to the S-Boxes) [abcd] = Z (Divide Z into four 8-bit quarters) Y = ((S1,a + S2,b mod 2^32) xor S3,c) + S4,d mod 2^32 This F-Function simulates a key-dependent Permutation and a 32:32-bit S-Box (Substitution) while actually using four 8:32-bit S-Boxes, which are combined using Addition and XOR. How to construct other Cobra variants: Let's assume one would like to use the Cobra-(48,256) variant: - The number of sub-blocks per block changes from 4 to 8, so the block length changes from 128 bit to 256 bit. - The number of P-Boxes changes from 24 to 48, because the number of rounds changes from 24 to 48. (use at least 6*(number of sub-blocks) rounds to get a good avalanche effect) - The maximum key length changes from (24/2*3*32)=1152 bit to (48/2*7*32)=5376 bit. - The number of entries per P-Box changes from 3 to 7. - The number of entries per W-Box changes from 4 to 8. And in the encryption/decryption routine the 32-bit sub-blocks must range from A to H instead of A,B,C,D. To encrypt the 256-bit data element, X, with Cobra-(48,256): Divide X into eight 32-bit sub-blocks: A,B,C,D,E,F,G,H A = A xor W1,1 B = B xor W1,2 C = C xor W1,3 D = D xor W1,4 E = E xor W1,5 F = F xor W1,6 G = G xor W1,7 H = H xor W1,8 For r = 1 to 48 A' = H B' = (A xor F(B;Pr,1))>>>1 C' = (B xor F(C;Pr,2))>>>1 D' = (C xor F(D;Pr,3))>>>1 E' = (D xor F(E;Pr,4))>>>1 F' = (E xor F(F;Pr,5))>>>1 G' = (F xor F(G;Pr,6))>>>1 H' = (G xor F(H;Pr,7))>>>1 A = A' B = B' C = C' D = D' E = E' F = F' G = G' H = H' Next r A = A xor W2,1 B = B xor W2,2 C = C xor W2,3 D = D xor W2,4 E = E xor W2,5 F = F xor W2,6 G = G xor W2,7 H = H xor W2,8 Finally recombine A,B,C,D,E,F,G,H to get the ciphertext. To decrypt the 256-bit data element, X, with Cobra-(48,256): Divide X into eight 32-bit sub-blocks: A,B,C,D,E,F,G,H A = A xor W2,1 B = B xor W2,2 C = C xor W2,3 D = D xor W2,4 E = E xor W2,5 F = F xor W2,6 G = G xor W2,7 H = H xor W2,8 For r = 48 to 1 H' = A G' = (H<<<1) xor F(H';Pr,7) F' = (G<<<1) xor F(G';Pr,6) E' = (F<<<1) xor F(F';Pr,5) D' = (E<<<1) xor F(E';Pr,4) C' = (D<<<1) xor F(D';Pr,3) B' = (C<<<1) xor F(C';Pr,2) A' = (B<<<1) xor F(B';Pr,1) A = A' B = B' C = C' D = D' E = E' F = F' G = G' H = H' Next r A = A xor W1,1 B = B xor W1,2 C = C xor W1,3 D = D xor W1,4 E = E xor W1,5 F = F xor W1,6 G = G xor W1,7 H = H xor W1,8 Finally recombine A,B,C,D,E,F,G,H to get the plaintext. _____________________________________________________________________ | Ciao, PGP-KeyID: EC2F4101 Created: 1995/05/14 | | Christian Schneider PGP-Fingerprint: 0A 24 32 F5 17 4A CD 19 | | E-Mail: 100542.2132@compuserve.com C7 FF 92 44 E4 5E 2D 42 | | Homepage: http://ourworld.compuserve.com/homepages/c_schneider | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Any comments or questions are welcome. - Chris