/******************************************************************************* * Copyright © 2011, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.compiler.internal.util; public class Tea { private int _key[]; // The 128 bit key. //?private byte _keyBytes[]; // original key as found private int _padding; //? amount of padding added in byte --> integer conversion. // constructors public Tea(int key[]) { _key = key; } public Tea(byte key[]) { int klen = key.length; _key = new int[4]; // Incorrect key length throws exception. if (klen != 16) throw new ArrayIndexOutOfBoundsException( this.getClass().getName() + ": Key is not 16 bytes: " + klen); //$NON-NLS-1$ int j, i; for (i = 0, j = 0; j < klen; j += 4, i++) _key[i] = (key[j] << 24) | (((key[j + 1]) & 0xff) << 16) | (((key[j + 2]) & 0xff) << 8) | ((key[j + 3]) & 0xff); //? _keyBytes = key; // save for toString. } /** * Byte wrapper for encoding. * Converts bytes to ints. * Padding will be added if required. * * @param b incoming <code>byte</code> array * * @param byte count * * @return integer conversion array, possibly with padding. * * @see #padding */ int[] encode(byte b[], int count) { int j, i; int bLen = count; byte bp[] = b; _padding = bLen % 8; if (_padding != 0) // Add some padding, if necessary. { _padding = 8 - (bLen % 8); bp = new byte[bLen + _padding]; System.arraycopy(b, 0, bp, 0, bLen); bLen = bp.length; } int intCount = bLen / 4; int r[] = new int[2]; int out[] = new int[intCount]; // System.out.println("Looping on " + intCount + " ints"); for (i = 0, j = 0; j < bLen; j += 8, i += 2) { // Java's unforgivable lack of unsigneds causes more bit // twiddling than this language really needs. r[0] = (bp[j] << 24) | (((bp[j + 1]) & 0xff) << 16) | (((bp[j + 2]) & 0xff) << 8) | ((bp[j + 3]) & 0xff); r[1] = (bp[j + 4] << 24) | (((bp[j + 5]) & 0xff) << 16) | (((bp[j + 6]) & 0xff) << 8) | ((bp[j + 7]) & 0xff); encipher(r); out[i] = r[0]; out[i + 1] = r[1]; } return out; } /** * Encipher two <code>int</code>s. * Replaces the original contents of the parameters with the results. * The integers are usually created from 8 bytes. * The usual way to collect bytes to the int array is: * <PRE> * byte ba[] = { .... }; * int v[] = new int[2]; * v[0] = (ba[j] << 24 ) | (((ba[j+1])&0xff) << 16) | (((ba[j+2])&0xff) << 8) | ((ba[j+3])&0xff); * v[1] = (ba[j+4] << 24 ) | (((ba[j+5])&0xff) << 16) | (((ba[j+6])&0xff) << 8) | ((ba[j+7])&0xff); * v = encipher(v); * </PRE> * * @param v two <code>int</code> array as input. * * @return array of two <code>int</code>s, enciphered. */ public int[] encipher(int v[]) { int y = v[0]; int z = v[1]; int sum = 0; int delta = 0x9E3779B9; int a = _key[0]; int b = _key[1]; int c = _key[2]; int d = _key[3]; int n = 32; while (n-- > 0) { sum += delta; y += (z << 4) + a ^ z + sum ^ (z >>> 5) + b; z += (y << 4) + c ^ y + sum ^ (y >>> 5) + d; } v[0] = y; v[1] = z; return v; } /** * Decode an integer array. * There may be some padding at the end of the byte array from * the previous encode operation. * * @param b bytes to decode * @param count number of bytes in the array to decode * * @return <code>byte</code> array of decoded bytes. */ public byte[] decode(int b[]) { // create the large number and start stripping ints out, two at a time. int intCount = b.length; byte outb[] = new byte[intCount * 4]; int tmp[] = new int[2]; // decipher all the ints. int i, j; for (j = 0, i = 0; i < intCount; i += 2, j += 8) { tmp[0] = b[i]; tmp[1] = b[i + 1]; decipher(tmp); outb[j] = (byte) (tmp[0] >>> 24); outb[j + 1] = (byte) (tmp[0] >>> 16); outb[j + 2] = (byte) (tmp[0] >>> 8); outb[j + 3] = (byte) (tmp[0]); outb[j + 4] = (byte) (tmp[1] >>> 24); outb[j + 5] = (byte) (tmp[1] >>> 16); outb[j + 6] = (byte) (tmp[1] >>> 8); outb[j + 7] = (byte) (tmp[1]); } return outb; } /** * Decipher two <code>int</code>s. * Replaces the original contents of the parameters with the results. * The integers are usually decocted to 8 bytes. * The decoction of the <code>int</code>s to bytes can be done * this way. * <PRE> * int x[] = decipher(ins); * outb[j] = (byte)(x[0] >>> 24); * outb[j+1] = (byte)(x[0] >>> 16); * outb[j+2] = (byte)(x[0] >>> 8); * outb[j+3] = (byte)(x[0]); * outb[j+4] = (byte)(x[1] >>> 24); * outb[j+5] = (byte)(x[1] >>> 16); * outb[j+6] = (byte)(x[1] >>> 8); * outb[j+7] = (byte)(x[1]); * </PRE> * * @param v <code>int</code> array of 2 * * @return deciphered <code>int</code> array of 2 */ public int[] decipher(int v[]) { int y = v[0]; int z = v[1]; int sum = 0xC6EF3720; int delta = 0x9E3779B9; int a = _key[0]; int b = _key[1]; int c = _key[2]; int d = _key[3]; int n = 32; // sum = delta<<5, in general sum = delta * n while (n-- > 0) { z -= (y << 4) + c ^ y + sum ^ (y >>> 5) + d; y -= (z << 4) + a ^ z + sum ^ (z >>> 5) + b; sum -= delta; } v[0] = y; v[1] = z; return v; } }