//============================================================================== // 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