Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java')
-rw-r--r--core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java188
1 files changed, 188 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java b/core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java
new file mode 100644
index 00000000..5dcb4ea1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/crypto/engines/XTEAEngine.java
@@ -0,0 +1,188 @@
+package org.spongycastle.crypto.engines;
+
+import org.spongycastle.crypto.BlockCipher;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.DataLengthException;
+import org.spongycastle.crypto.OutputLengthException;
+import org.spongycastle.crypto.params.KeyParameter;
+
+/**
+ * An XTEA engine.
+ */
+public class XTEAEngine
+ implements BlockCipher
+{
+ private static final int rounds = 32,
+ block_size = 8,
+// key_size = 16,
+ delta = 0x9E3779B9;
+
+ /*
+ * the expanded key array of 4 subkeys
+ */
+ private int[] _S = new int[4],
+ _sum0 = new int[32],
+ _sum1 = new int[32];
+ private boolean _initialised,
+ _forEncryption;
+
+ /**
+ * Create an instance of the TEA encryption algorithm
+ * and set some defaults
+ */
+ public XTEAEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "XTEA";
+ }
+
+ public int getBlockSize()
+ {
+ return block_size;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + block_size) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + block_size) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ * <p>
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ if (key.length != 16)
+ {
+ throw new IllegalArgumentException("Key size must be 128 bits.");
+ }
+
+ int i, j;
+ for (i = j = 0; i < 4; i++,j+=4)
+ {
+ _S[i] = bytesToInt(key, j);
+ }
+
+ for (i = j = 0; i < rounds; i++)
+ {
+ _sum0[i] = (j + _S[j & 3]);
+ j += delta;
+ _sum1[i] = (j + _S[j >>> 11 & 3]);
+ }
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ for (int i = 0; i < rounds; i++)
+ {
+ v0 += ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
+ v1 += ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ for (int i = rounds-1; i >= 0; i--)
+ {
+ v1 -= ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
+ v0 -= ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int bytesToInt(byte[] in, int inOff)
+ {
+ return ((in[inOff++]) << 24) |
+ ((in[inOff++] & 255) << 16) |
+ ((in[inOff++] & 255) << 8) |
+ ((in[inOff] & 255));
+ }
+
+ private void unpackInt(int v, byte[] out, int outOff)
+ {
+ out[outOff++] = (byte)(v >>> 24);
+ out[outOff++] = (byte)(v >>> 16);
+ out[outOff++] = (byte)(v >>> 8);
+ out[outOff ] = (byte)v;
+ }
+}