//============================================================================== // ZoidfarbCipher.java //============================================================================== package tribble.crypto; // System imports import java.lang.CloneNotSupportedException; import java.lang.Exception; import java.lang.NullPointerException; import java.lang.String; import java.security.InvalidKeyException; /******************************************************************************* * Zoidfarb cryptographic symmetric block cipher. * Encrypts or decrypts a 160-bit (20-byte) data block using a 128-bit symmetric * encryption key. * *
* Note that none of these methods are synchronized. * * *
* Acknowledgments *
* This code is based on an original algorithm invented by David R. Tribble in * April 2003. * This is version "C" of the algorithm. * *
* License is granted to use this algorithm without fees or restrictions for all * private and commercial uses. * * * @version API 2, $Revision: 1.6 $ $Date: 2005/09/11 15:17:34 $ * @since 2003-04-07 * @author * David R Tribble * (david@tribble.com). * *
* Copyright ©2003-2005 by David R. Tribble, all rights reserved.
*
* Permission is granted to freely use and distribute this source code
* provided that the original copyright and authorship notices remain
* intact.
*
* @see tribble.security.ZoidfarbHash
*/
public class ZoidfarbCipher
extends tribble.crypto.SymmetricCipher
{
// Identification
/** Revision information. */
static final String REV =
"@(#)tribble/crypto/ZoidfarbCipher.java $Revision: 1.6 $ $Date: 2005/09/11 15:17:34 $\n";
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Constants
/** Cipher algorithm name. */
private static final String ALGORITHM = "ZoidfarbCipher";
/** Cipher block size (20 bytes, 160 bits). */
private static final short BLOCK_SIZE = 160/8;
/** Cipher key size (16 bytes, 128 bits). */
private static final short KEY_SIZE = 128/8;
//----------------------------------
// Test vectors (see #main)
private static final byte[] TEST_KEY1 =
{
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
};
private static final byte[] TEST_PLAINTEXT1 =
{
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
};
private static final byte[] TEST_KEY2 =
{
(byte) 0x44, (byte) 0x61, (byte) 0x76, (byte) 0x69,
(byte) 0x64, (byte) 0x20, (byte) 0x52, (byte) 0x2E,
(byte) 0x20, (byte) 0x54, (byte) 0x72, (byte) 0x69,
(byte) 0x62, (byte) 0x62, (byte) 0x6C, (byte) 0x65,
};
private static final byte[] TEST_PLAINTEXT2 =
{
(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67,
(byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0xFF, (byte) 0x01, (byte) 0x80, (byte) 0xFF,
(byte) 0xA5, (byte) 0xC3, (byte) 0xB4, (byte) 0x81,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Static methods
/***************************************************************************
* Test driver.
*
* @param args
* Command line arguments.
*
* @throws Exception
* Thrown if an error occurs in the encryption engine.
*
* @since 1.1, 2003-04-06
*/
public static final void main(String[] args)
throws Exception
{
// Check args
if (args.length == 0)
{
// Test this cipher
test(new ZoidfarbCipher(), TEST_KEY1, TEST_PLAINTEXT1);
test(new ZoidfarbCipher(), TEST_KEY2, TEST_PLAINTEXT2);
}
else
{
/*+++NEW, INCOMPLETE
boolean opt_encrypt;
byte[] key;
// Check args
if (args.length < 2)
usage();
// Get encrypt/decrypt option
if (args[0].equals("-e"))
opt_encrypt = true;
else if (args[0].equals("-d"))
opt_encrypt = false;
else
usage();
// Get the encryption key from the password arg
key = KeyMaker.makeKey??(args[0], KEY_SIZE);
if (args.length > 1)
{
// Encrypt/decrypt the command line arguments
...;
}
else
{
// Encrypt/decrypt data read from standard input
...;
}
+++*/
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Variables
//----------------------------------
// Subkey schedule (5x32=160 bits), derived from the encryption key
private int m_k0;
private int m_k1;
private int m_k2;
private int m_k3;
private int m_k4;
//----------------------------------
// Input block words (5x32=160 bits)
private int m_in0;
private int m_in1;
private int m_in2;
private int m_in3;
private int m_in4;
//----------------------------------
// Output block words (5x32=160 bits)
private int m_out0;
private int m_out1;
private int m_out2;
private int m_out3;
private int m_out4;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Constructors
/***************************************************************************
* Default constructor.
*
* @since 1.1, 2002-05-23
*/
public ZoidfarbCipher()
{
// Initialize
super(ALGORITHM, BLOCK_SIZE);
m_keyLen = KEY_SIZE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Methods
/***************************************************************************
* Initialize this cipher.
*
* @param key
* The symmetric (secret) key for this cipher.
*
* @param decrypt
* If true, this indicates that this cipher is to be initialized for
* decrypting, otherwise it is to be initialized for encrypting.
*
* @see #clear clear()
*
* @since 1.1, 2002-04-26
*/
protected void initialize(byte[] key, boolean decrypt)
throws InvalidKeyException
//overrides tribble.crypto.SymmetricCipher
{
// Check the key
if (key == null)
throw new InvalidKeyException("Key missing");
if (key.length != KEY_SIZE)
throw new InvalidKeyException("Invalid key length");
// Generate the cipher subkey schedule
makeKey(key);
}
/***************************************************************************
* Clear (wipe) this cipher.
* Erases all sensitive information contained within this object.
*
*
* Note that this cipher object can no longer be used after this method has * been called. * * @since 1.5, 2004-12-20 */ protected void clear() //overrides tribble.crypto.SymmetricCipher { // Wipe the subkey schedule m_k0 = -1; m_k1 = -1; m_k2 = -1; m_k3 = -1; m_k4 = -1; // Wipe the input block words m_in0 = 0; m_in1 = 0; m_in2 = 0; m_in3 = 0; m_in4 = 0; // Wipe the output block words m_out0 = 0; m_out1 = 0; m_out2 = 0; m_out3 = 0; m_out4 = 0; } /*************************************************************************** * Encrypt a block of plaintext. * * @param in * Array containing a single block of plaintext bytes to encrypt. * The length of the block is exactly equal to the cipher block size * (160 bits, 20 bytes). * * @param inOff * Index of the first byte of the plaintext block within array in to * encrypt. * * @param out * Array that will be filled with the encrypted ciphertext block. * The length of the block is exactly equal to the cipher block size * (160 bits, 20 bytes). * * @param outOff * Index of the first byte of array out to fill with the encrypted * ciphertext block. * * @see #blockDecrypt blockDecrypt() * @see #initialize initialize() * * @since 1.1, 2002-04-26 */ protected void blockEncrypt(/*const*/ byte[] in, int inOff, byte[] out, int outOff) //overrides tribble.crypto.SymmetricCipher { // Encrypt the input block unpackInput(in, inOff); encrypt(); packOutput(out, outOff); } /*************************************************************************** * Decrypt a block of ciphertext. * * @param in * Array containing a single block of ciphertext bytes to decrypt. * The length of the block is exactly equal to the cipher block size * (160 bits, 20 bytes). * * @param inOff * Index of the first byte of the ciphertext block within array in * to decrypt. * * @param out * Array that will be filled with the decrypted plaintext block. * The length of the block is exactly equal to the cipher block size * (160 bits, 20 bytes). * * @param outOff * Index of the first byte of array out to fill with the decrypted * plaintext block. * * @see #blockEncrypt blockEncrypt() * @see #initialize initialize() * * @since 1.1, 2002-04-26 */ protected void blockDecrypt(/*const*/ byte[] in, int inOff, byte[] out, int outOff) //overrides tribble.crypto.SymmetricCipher { // Decrypt the input block unpackInput(in, inOff); decrypt(); packOutput(out, outOff); } /*************************************************************************** * Establish the encryption subkey schedule. * *
* The 128-bit encryption key is expanded into a 160-bit subkey schedule: *
* +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |e f g h| |i j k l| |m n o p| Key (4x32=128 bits) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : * : : : : : * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |d'e f g| |g'h i j| |j'k l m| |m'n o p| Subkeys (160 bits) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | k0 | | k1 | | k2 | | k3 | | k4 | K (5x32=160 bits) * +-----+ +-----+ +-----+ +-----+ +-----+ ** *
* Individual octets marked with a prime (e.g., d') are * complemented, to insure that the resulting subkeys are not all zeros or * all ones. * * @param key * Encryption/decryption key, which must be exactly 128 bits (16 bytes) long. * * @since 1.1, 2002-05-23 */ private void makeKey(byte[] key) { int ka; int kb; // Compute the subkey schedule, spreading 128 bits across 160 bits kb = (key[0] & 0xFF); kb = (kb << 8) + (key[1] & 0xFF); kb = (kb << 8) + (key[2] & 0xFF); kb = (kb << 8) + (key[3] & 0xFF); m_k0 = kb; ka = kb; kb = (key[4] & 0xFF); kb = (kb << 8) + (key[5] & 0xFF); kb = (kb << 8) + (key[6] & 0xFF); kb = (kb << 8) + (key[7] & 0xFF); m_k1 = ((ka << 32-8*1) | (kb >>> 8*1)) ^ 0xFF000000; ka = kb; kb = (key[8] & 0xFF); kb = (kb << 8) + (key[9] & 0xFF); kb = (kb << 8) + (key[10] & 0xFF); kb = (kb << 8) + (key[11] & 0xFF); m_k2 = ((ka << 32-8*2) | (kb >>> 8*2)) ^ 0xFF000000; ka = kb; kb = (key[12] & 0xFF); kb = (kb << 8) + (key[13] & 0xFF); kb = (kb << 8) + (key[14] & 0xFF); kb = (kb << 8) + (key[15] & 0xFF); m_k3 = ((ka << 32-8*3) | (kb >>> 8*3)) ^ 0xFF000000; m_k4 = kb ^ 0xFF000000; } /*************************************************************************** * Extract 20 8-bit input bytes into 5 32-bit input words. * * @param in * Array containing a single block of bytes to encrypt/decrypt. * The length of the block is exactly equal to the cipher block size * (160 bits, 20 bytes). * * @param inOff * Index of the first byte of the block within array in to * encrypt/decrypt. * * @since 1.6, 2005-09-11 */ private void unpackInput(/*const*/ byte[] in, int inOff) { // Extract 20 8-bit input bytes into 5 32-bit input words m_in0 = ((((( (in[inOff+0] & 0xFF) << 8) + (in[inOff+1] & 0xFF)) << 8) + (in[inOff+2] & 0xFF)) << 8) + (in[inOff+3] & 0xFF); inOff += 4; m_in1 = ((((( (in[inOff+0] & 0xFF) << 8) + (in[inOff+1] & 0xFF)) << 8) + (in[inOff+2] & 0xFF)) << 8) + (in[inOff+3] & 0xFF); inOff += 4; m_in2 = ((((( (in[inOff+0] & 0xFF) << 8) + (in[inOff+1] & 0xFF)) << 8) + (in[inOff+2] & 0xFF)) << 8) + (in[inOff+3] & 0xFF); inOff += 4; m_in3 = ((((( (in[inOff+0] & 0xFF) << 8) + (in[inOff+1] & 0xFF)) << 8) + (in[inOff+2] & 0xFF)) << 8) + (in[inOff+3] & 0xFF); inOff += 4; m_in4 = ((((( (in[inOff+0] & 0xFF) << 8) + (in[inOff+1] & 0xFF)) << 8) + (in[inOff+2] & 0xFF)) << 8) + (in[inOff+3] & 0xFF); } /*************************************************************************** * Extract 5 32-bit output words into 20 8-bit output bytes. * * @param out * Array that will be filled with the encrypted/decrypted block. * The length of the block is exactly equal to the cipher block size * (160 bits, 20 bytes). * * @param outOff * Index of the first byte of array out to fill with the * encrypted/decrypted output block. * * @since 1.6, 2005-09-11 */ private void packOutput(byte[] out, int outOff) /*const*/ { int o; // Extract 5 32-bit output words into 20 8-bit output bytes o = m_out0; out[outOff++] = (byte) (o >>> 8*3); out[outOff++] = (byte) (o >>> 8*2); out[outOff++] = (byte) (o >>> 8*1); out[outOff++] = (byte) (o); o = m_out1; out[outOff++] = (byte) (o >>> 8*3); out[outOff++] = (byte) (o >>> 8*2); out[outOff++] = (byte) (o >>> 8*1); out[outOff++] = (byte) (o); o = m_out2; out[outOff++] = (byte) (o >>> 8*3); out[outOff++] = (byte) (o >>> 8*2); out[outOff++] = (byte) (o >>> 8*1); out[outOff++] = (byte) (o); o = m_out3; out[outOff++] = (byte) (o >>> 8*3); out[outOff++] = (byte) (o >>> 8*2); out[outOff++] = (byte) (o >>> 8*1); out[outOff++] = (byte) (o); o = m_out4; out[outOff++] = (byte) (o >>> 8*3); out[outOff++] = (byte) (o >>> 8*2); out[outOff++] = (byte) (o >>> 8*1); out[outOff] = (byte) (o); } /*************************************************************************** * Encrypt a single 160-bit (20-byte) input block of plaintext. * *
* Algorithm * *
* The encryption algorithm is a "braiding" of five 32-bit binary words, * which comprise a total of 160 bits of the cipher block. The "braiding" * refers to the way in which the words are permuted (rearranged). Between * each permuting operation (Pi-phase), the output of the permutation * is combined with the subkeys, using exclusive-or (X-phase) and * two's-complement addition (A-phase) operations. * *
* The 128-bit encryption key is expanded into a 160-bit subkey schedule: *
* +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |e f g h| |i j k l| |m n o p| Key (4x32=128 bits) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : * : : : : : * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |d'e f g| |g'h i j| |j'k l m| |m'n o p| Subkeys (160 bits) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | k0 | | k1 | | k2 | | k3 | | k4 | K (5x32=160 bits) * +-----+ +-----+ +-----+ +-----+ +-----+ ** *
* Individual octets marked with a prime (e.g., d') are * complemented, to insure that the resulting subkeys are not all zeros or * all ones. * *
* KXi = KAi = Ki.
*
* Each round uses key input vectors KXi and KAi, which are both identical to
* the 160-bit key vector Ki.
* After each iteration, the key vector is modified:
*
* K0i = K0i + 0xA562F620; * K1i = K1i + 0x5C8ACB59; * K2i = K2i + 0x30330333; * K3i = K3i + 0x70F9435E; * K4i = K4i + 0x05550555; ** *
* The cipher uses 10 pairs of key vectors (KX1/KA1 through KX10/KA10), each * pair being derived from the pair used in the previous round. That is, * keys KX2 and KA2 are derived from KX1 and KA1, and so forth. This simple * scrambling of the initial key vector can be viewed as infusing a total of * 3,200 bits (10 x 2 x 160 bits) of key material into the rounds. * *
* The I vector is the input cipher data (160 bits) of each phase, which is * fed into the other phases of the algorithm. The R, P1, X, S, P2, and A * phases comprise a single round, which is repeated 10 times, intermixing * the contents of the input vector with the cipher vector. The final result * of the intermixing is the output cipher vector O. * * *
* Complete sequence: *
* +----+----+----+----+----+ * | i0 | i1 | i2 | i3 | i4 | I, Input (5x32=160 bits) * +----+----+----+----+----+ * : : : : : * +------------------------+ +----+----+----+----+----+ * | Round 1 |<-- | k0 | k1 | k2 | k3 | k4 | Key KX1 * | | +----+----+----+----+----+ * | |<-- | k0 | k1 | k2 | k3 | k4 | Key KA1 * +------------------------+ +----+----+----+----+----+ (160 bits) * : : : : : * +------------------------+ +----+----+----+----+----+ * | Round 2 |<-- | k0 | k1 | k2 | k3 | k4 | Key KX2 * | | +----+----+----+----+----+ * | |<-- | k0 | k1 | k2 | k3 | k4 | Key KA2 * +------------------------+ +----+----+----+----+----+ (160 bits) * : : : : : * etc. * : : : : : * +------------------------+ +----+----+----+----+----+ * | Round 10 |<-- | k0 | k1 | k2 | k3 | k4 | Key KX10 * | | +----+----+----+----+----+ * | |<-- | k0 | k1 | k2 | k3 | k4 | Key KA10 * +------------------------+ +----+----+----+----+----+ (160 bits) * : : : : : * +----+----+----+----+----+ * | o0 | o1 | o2 | o3 | o4 | O, Output (5x32=160 bits) * +----+----+----+----+----+ ** * *
* Each round is composed of a sequence of bit rotations, word-wise * permutation, bitwise exclusive-oring with the key, and bitwise addition * with the key. Each step (phase) in the round is illustrated here: * *
* I-phase: * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |e f g h| |i j k l| |m n o p| |q r s t| Input bytes (20) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | i0 | | i1 | | i2 | | i3 | | i4 | I (5x32=160 bits) * +-----+ +-----+ +-----+ +-----+ +-----+ * * R-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | i0 | | i1 | | i2 | | i3 | | i4 | Ii * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * ROR(17) ROR(5) ROR(25) ROR(13) ROR(29) * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Ri * +-----+ +-----+ +-----+ +-----+ +-----+ * * P1-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Ri * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * : : : : : * : : : : : * : :: : : * : : : : : * : : :: : * : : : : : * : : : : : * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | B | | C | | D | | E | | A | P1i * +-----+ +-----+ +-----+ +-----+ +-----+ * * X-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | P1i * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * | k0 | : | k1 | : | k2 | : | k3 | : | k4 | : Key KXi * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * : : : : : : : : : : * : NEG : : : : : : : : * : : : : : : : : : : * : : : : : : : : : : * XOR XOR XOR XOR XOR * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Xi * +-----+ +-----+ +-----+ +-----+ +-----+ * * S-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Xi * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * +-------------------------------+ * | ROL(16) | * +-------------------------------+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Si * +-----+ +-----+ +-----+ +-----+ +-----+ * * P2-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Si * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * : : : : : * : : : : * :: : : : * : : : : : * : : : :: * : : : : * : : : : : * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | B | | D | | A | | E | | C | P2i * +-----+ +-----+ +-----+ +-----+ +-----+ * * A-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | P2i * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * | k0 | : | k1 | : | k2 | : | k3 | : | k4 | : Key KAi * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * : : : : : : : : : : * : : : : : : : : : : * ADD ADD ADD ADD ADD * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Ai * +-----+ +-----+ +-----+ +-----+ +-----+ * * Ai becomes Ii for the next round. ** *
* The P1 and P2 phases permute the 5 words of the cipher vector in the * following braiding pattern (which repeats every 5 rounds): * *
*
* 0. A B C D E * 1. B C D E A P1 round 1 * 2. C E B A D P2 * 3. E B A D C P1 round 2 * 4. B D E C A P2 * 5. D E C A B P1 round 3 * 6. E A D B C P2 * 7. A D B C E P1 round 4 * 8. D C A E B P2 * 9. C A E B D P1 round 5 * 10. A B C D E P2 ** * *
* Test Vectors * *
* 1.
* An input block of
* {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00}
*
* with a key of
* {00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00}
*
* encrypts to an output block of
* {BE 82 D5 38 FB 49 22 FF E6 31 B4 F2 45 F2 9C 1E B6 EC 5B 7A}.
*
*
* 2.
* An input block of
* {01 23 45 67 89 AB CD EF 00 00 00 00 FF 01 80 FF A5 C3 B4 81}
*
* with a key of
* {44 61 76 69 64 20 52 2E 20 54 72 69 62 62 6C 65}
*
* encrypts to an output block of
* {73 5C FE 1B 25 F4 8C BA BA 1E C5 E2 35 43 2F C1 2A 8F C3 1F}.
*
* @see #decrypt decrypt()
* @see #makeKey makeKey()
*
* @since 1.1, 2003-04-06
*/
private void encrypt()
{
int i0, i1, i2, i3, i4;
int k0, k1, k2, k3, k4;
// Get the words of the input block
i0 = m_in0;
i1 = m_in1;
i2 = m_in2;
i3 = m_in3;
i4 = m_in4;
// Get the words of the key
k0 = m_k0;
k1 = m_k1;
k2 = m_k2;
k3 = m_k3;
k4 = m_k4;
// Encipher, using multiple braiding rounds
for (int i = 10; i > 0; i--)
{
int o0, o1, o2, o3, o4;
int t;
// R-phase: Rotate the I(i) cipher words by various amounts
o0 = (i0 >>> 17) | (i0 << 32-17);
o1 = (i1 >>> 5) | (i1 << 32- 5);
o2 = (i2 >>> 25) | (i2 << 32-25);
o3 = (i3 >>> 13) | (i3 << 32-13);
o4 = (i4 >>> 29) | (i4 << 32-29);
// P1-phase: Permute (braid) the R(i) cipher words
t = o0;
o0 = o1;
o1 = o2;
o2 = o3;
o3 = o4;
o4 = t;
// X-phase: Exclusive-or the P1(i) cipher vector with Key KX(i)
o0 = -o0 ^ k0;
o1 ^= k1;
o2 ^= k2;
o3 ^= k3;
o4 ^= k4;
// Permute the key vector for the next round
k0 += 0xA562F620;
k1 += 0x5C8ACB59;
k2 += 0x30330333;
k3 += 0x70F9435E;
k4 += 0x05550555;
// S-phase: Rotate the entire vector by 16 bits
t = o0;
o0 = (o0 << 16) | (o1 >>> 32-16);
o1 = (o1 << 16) | (o2 >>> 32-16);
o2 = (o2 << 16) | (o3 >>> 32-16);
o3 = (o3 << 16) | (o4 >>> 32-16);
o4 = (o4 << 16) | (t >>> 32-16);
// P2-phase: Permute (braid) the X(i) cipher words
t = o0;
o0 = o1;
o1 = o3;
o3 = o4;
o4 = o2;
o2 = t;
// A-phase: Add the P2(i) cipher vector to Key KA(i)
i0 = o0 + k0;
i1 = o1 + k1;
i2 = o2 + k2;
i3 = o3 + k3;
i4 = o4 + k4;
// The input cipher vector I(i+1) for the next round is A(i)
}
// Update the output cipher vector with A(n)
m_out0 = i0;
m_out1 = i1;
m_out2 = i2;
m_out3 = i3;
m_out4 = i4;
}
/***************************************************************************
* Decrypt a single 160-bit (20-byte) input block of ciphertext.
*
*
* Algorithm * *
* Decrypting a previously encrypted block is done by applying inverse * operations of each of the encryption phases in reverse order using * inverted subkeys. * *
* The 128-bit encryption key is expanded into a 160-bit subkey schedule: *
* +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |e f g h| |i j k l| |m n o p| Key (4x32=128 bits) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : * : : : : : * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |d'e f g| |g'h i j| |j'k l m| |m'n o p| Subkeys (160 bits) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | k0 | | k1 | | k2 | | k3 | | k4 | K (5x32=160 bits) * +-----+ +-----+ +-----+ +-----+ +-----+ ** *
* Individual octets marked with a prime (e.g., d') are * complemented, to insure that the resulting subkeys are not all zeros or * all ones. * *
* For a given encryption subkey KXi for the X (exclusive-or) phase, the * inverse subkey KXi' is equal to KXi (since exclusive-or is its own inverse * operation). * *
* For a given encryption subkey KAi for the A (addition) phase, the inverse * subkey KAi' is the additive inverse (i.e., the two's-complement or * negation) of KAi. (Adding the additive inverse of a subkey is, of course, * equivalent to subtracting the subkey.) * *
* KXi' = KXi = Ki (exclusive-or inverse).
* KAi' = -KAi = -Ki (additive inverse).
*
*
* Note that the decryption process applies the algorithm rounds (i.e., the * round keys) in the reverse order as encryption. * * *
* Complete sequence: *
* +----+----+----+----+----+ * | i0 | i1 | i2 | i3 | i4 | I, Input (5x32=160 bits) * +----+----+----+----+----+ * : : : : : * +------------------------+ +----+----+----+----+----+ * | Round 1 |<-- | k0 | k1 | k2 | k3 | k4 | Key KX'10 * | | +----+----+----+----+----+ * | |<-- | k0 | k1 | k2 | k3 | k4 | Key KA'10 * +------------------------+ +----+----+----+----+----+ (160 bits) * : : : : : * +------------------------+ +----+----+----+----+----+ * | Round 2 |<-- | k0 | k1 | k2 | k3 | k4 | Key KX'9 * | | +----+----+----+----+----+ * | |<-- | k0 | k1 | k2 | k3 | k4 | Key KA'9 * +------------------------+ +----+----+----+----+----+ (160 bits) * : : : : : * etc. * : : : : : * +------------------------+ +----+----+----+----+----+ * | Round 10 |<-- | k0 | k1 | k2 | k3 | k4 | Key KX'1 * | | +----+----+----+----+----+ * | |<-- | k0 | k1 | k2 | k3 | k4 | Key KA'1 * +------------------------+ +----+----+----+----+----+ (160 bits) * : : : : : * +----+----+----+----+----+ * | o0 | o1 | o2 | o3 | o4 | O, Output (5x32=160 bits) * +----+----+----+----+----+ ** * *
* Each round: *
* I-phase: * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * |a b c d| |e f g h| |i j k l| |m n o p| |q r s t| Input bytes (20) * +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ +-+-+-+-+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | i0 | | i1 | | i2 | | i3 | | i4 | I (5x32=160 bits) * +-----+ +-----+ +-----+ +-----+ +-----+ * * A'-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | i0 | | i1 | | i2 | | i3 | | i4 | Ii * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * | k0' | : | k1' | : | k2' | : | k3' | : | k4' | : Key KAi' * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * : : : : : : : : : : * : : : : : : : : : : * ADD ADD ADD ADD ADD * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Ai * +-----+ +-----+ +-----+ +-----+ +-----+ * * P2'-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Ai * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * : : : : : * : : : : * : : : :: * : : : : : * :: : : : * : : : : * : : : : : * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | C | | A | | E | | B | | D | P2i * +-----+ +-----+ +-----+ +-----+ +-----+ * * S'-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | P2i * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * +-------------------------------+ * | ROR(16) | * +-------------------------------+ * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Si * +-----+ +-----+ +-----+ +-----+ +-----+ * * X'-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Si * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * | k'0 | : | k'1 | : | k'2 | : | k'3 | : | k'4 | : Key KX'i * +-----+ : +-----+ : +-----+ : +-----+ : +-----+ : * : : : : : : : : : : * : : : : : : : : : : * XOR XOR XOR XOR XOR * : : : : : * NEG : : : : * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Xi * +-----+ +-----+ +-----+ +-----+ +-----+ * * P1'-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Xi * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * : : : : : * : : : : : * : : :: : * : : : : : * : :: : : * : : : : : * : : : : : * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | E | | A | | B | | C | | D | P1i * +-----+ +-----+ +-----+ +-----+ +-----+ * * R'-phase: * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | P1i * +-----+ +-----+ +-----+ +-----+ +-----+ * : : : : : * ROL(17) ROL(5) ROL(25) ROL(13) ROL(29) * : : : : : * +-----+ +-----+ +-----+ +-----+ +-----+ * | A | | B | | C | | D | | E | Ri * +-----+ +-----+ +-----+ +-----+ +-----+ * * Ri becomes Ii for the next round. ** * @see #encrypt encrypt() * @see #makeKey makeKey() * * @since 1.1, 2003-04-06 */ private void decrypt() { int i0, i1, i2, i3, i4; int k0, k1, k2, k3, k4; // Get the words of the input block i0 = m_in0; i1 = m_in1; i2 = m_in2; i3 = m_in3; i4 = m_in4; // Initialize the words of the key k0 = m_k0 + 10*0xA562F620; // + 0x75DD9D40 k1 = m_k1 + 10*0x5C8ACB59; // + 0x9D6BF17A k2 = m_k2 + 10*0x30330333; // + 0xE1FE1FFE k3 = m_k3 + 10*0x70F9435E; // + 0x69BCA1AC k4 = m_k4 + 10*0x05550555; // + 0x35523552 // Encipher, using multiple braiding rounds for (int i = 10; i > 0; i--) { int o0, o1, o2, o3, o4; int t; // A-phase: Add (subtract) the P2(i) cipher vector to Key KA'(i) o0 = i0 - k0; o1 = i1 - k1; o2 = i2 - k2; o3 = i3 - k3; o4 = i4 - k4; // P2'-phase: Permute (braid) the X(i) cipher words t = o0; o0 = o2; o2 = o4; o4 = o3; o3 = o1; o1 = t; // S-phase: Rotate the entire vector by 16 bits t = o4; o4 = (o4 >>> 16) | (o3 << 32-16); o3 = (o3 >>> 16) | (o2 << 32-16); o2 = (o2 >>> 16) | (o1 << 32-16); o1 = (o1 >>> 16) | (o0 << 32-16); o0 = (o0 >>> 16) | (t << 32-16); // Permute the key vector for the next round k0 -= 0xA562F620; k1 -= 0x5C8ACB59; k2 -= 0x30330333; k3 -= 0x70F9435E; k4 -= 0x05550555; // X-phase: Exclusive-or the P1(i) cipher vector with Key KX'(i) o0 = -(o0 ^ k0); o1 ^= k1; o2 ^= k2; o3 ^= k3; o4 ^= k4; // P1'-phase: Permute (braid) the R(i) cipher words t = o0; o0 = o4; o4 = o3; o3 = o2; o2 = o1; o1 = t; // R'-phase: Rotate the I(i) cipher words by various amounts i0 = (o0 >>> 32-17) | (o0 << 17); i1 = (o1 >>> 32- 5) | (o1 << 5); i2 = (o2 >>> 32-25) | (o2 << 25); i3 = (o3 >>> 32-13) | (o3 << 13); i4 = (o4 >>> 32-29) | (o4 << 29); // The input cipher vector I(i+1) for the next round is A(i) } // Update the output cipher vector with A(n) m_out0 = i0; m_out1 = i1; m_out2 = i2; m_out3 = i3; m_out4 = i4; } } // End ZoidfarbCipher.java