001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.security;
007:
008: import org.h2.constant.SysProperties;
009: import org.h2.message.Message;
010:
011: /**
012: * An implementation of the XTEA block cipher algorithm.
013: * This implementation uses 32 rounds.
014: */
015: public class XTEA implements BlockCipher {
016:
017: // TODO maybe implement Blowfish
018:
019: // best attack reported as of 2004 is 26 rounds [wikipedia]
020: private static final int DELTA = 0x9E3779B9;
021: private int k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12,
022: k13, k14, k15;
023: private int k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26,
024: k27, k28, k29, k30, k31;
025:
026: public void setKey(byte[] b) {
027: int[] key = new int[4];
028: for (int i = 0; i < 16;) {
029: key[i / 4] = (b[i++] << 24) + ((b[i++] & 255) << 16)
030: + ((b[i++] & 255) << 8) + (b[i++] & 255);
031: }
032: int[] r = new int[32];
033: for (int i = 0, sum = 0; i < 32;) {
034: r[i++] = sum + key[sum & 3];
035: sum += DELTA;
036: r[i++] = sum + key[(sum >>> 11) & 3];
037: }
038: k0 = r[0];
039: k1 = r[1];
040: k2 = r[2];
041: k3 = r[3];
042: k4 = r[4];
043: k5 = r[5];
044: k6 = r[6];
045: k7 = r[7];
046: k8 = r[8];
047: k9 = r[9];
048: k10 = r[10];
049: k11 = r[11];
050: k12 = r[12];
051: k13 = r[13];
052: k14 = r[14];
053: k15 = r[15];
054: k16 = r[16];
055: k17 = r[17];
056: k18 = r[18];
057: k19 = r[19];
058: k20 = r[20];
059: k21 = r[21];
060: k22 = r[22];
061: k23 = r[23];
062: k24 = r[24];
063: k25 = r[25];
064: k26 = r[26];
065: k27 = r[27];
066: k28 = r[28];
067: k29 = r[29];
068: k30 = r[30];
069: k31 = r[31];
070: }
071:
072: public void encrypt(byte[] bytes, int off, int len) {
073: if (SysProperties.CHECK && (len % ALIGN != 0)) {
074: throw Message.getInternalError("unaligned len " + len);
075: }
076: for (int i = off; i < off + len; i += 8) {
077: encryptBlock(bytes, bytes, i);
078: }
079: }
080:
081: public void decrypt(byte[] bytes, int off, int len) {
082: if (SysProperties.CHECK && (len % ALIGN != 0)) {
083: throw Message.getInternalError("unaligned len " + len);
084: }
085: for (int i = off; i < off + len; i += 8) {
086: decryptBlock(bytes, bytes, i);
087: }
088: }
089:
090: public void encryptBlock(byte[] in, byte[] out, int off) {
091: int y = (in[off] << 24) | ((in[off + 1] & 255) << 16)
092: | ((in[off + 2] & 255) << 8) | (in[off + 3] & 255);
093: int z = (in[off + 4] << 24) | ((in[off + 5] & 255) << 16)
094: | ((in[off + 6] & 255) << 8) | (in[off + 7] & 255);
095: y += (((z << 4) ^ (z >>> 5)) + z) ^ k0;
096: z += (((y >>> 5) ^ (y << 4)) + y) ^ k1;
097: y += (((z << 4) ^ (z >>> 5)) + z) ^ k2;
098: z += (((y >>> 5) ^ (y << 4)) + y) ^ k3;
099: y += (((z << 4) ^ (z >>> 5)) + z) ^ k4;
100: z += (((y >>> 5) ^ (y << 4)) + y) ^ k5;
101: y += (((z << 4) ^ (z >>> 5)) + z) ^ k6;
102: z += (((y >>> 5) ^ (y << 4)) + y) ^ k7;
103: y += (((z << 4) ^ (z >>> 5)) + z) ^ k8;
104: z += (((y >>> 5) ^ (y << 4)) + y) ^ k9;
105: y += (((z << 4) ^ (z >>> 5)) + z) ^ k10;
106: z += (((y >>> 5) ^ (y << 4)) + y) ^ k11;
107: y += (((z << 4) ^ (z >>> 5)) + z) ^ k12;
108: z += (((y >>> 5) ^ (y << 4)) + y) ^ k13;
109: y += (((z << 4) ^ (z >>> 5)) + z) ^ k14;
110: z += (((y >>> 5) ^ (y << 4)) + y) ^ k15;
111: y += (((z << 4) ^ (z >>> 5)) + z) ^ k16;
112: z += (((y >>> 5) ^ (y << 4)) + y) ^ k17;
113: y += (((z << 4) ^ (z >>> 5)) + z) ^ k18;
114: z += (((y >>> 5) ^ (y << 4)) + y) ^ k19;
115: y += (((z << 4) ^ (z >>> 5)) + z) ^ k20;
116: z += (((y >>> 5) ^ (y << 4)) + y) ^ k21;
117: y += (((z << 4) ^ (z >>> 5)) + z) ^ k22;
118: z += (((y >>> 5) ^ (y << 4)) + y) ^ k23;
119: y += (((z << 4) ^ (z >>> 5)) + z) ^ k24;
120: z += (((y >>> 5) ^ (y << 4)) + y) ^ k25;
121: y += (((z << 4) ^ (z >>> 5)) + z) ^ k26;
122: z += (((y >>> 5) ^ (y << 4)) + y) ^ k27;
123: y += (((z << 4) ^ (z >>> 5)) + z) ^ k28;
124: z += (((y >>> 5) ^ (y << 4)) + y) ^ k29;
125: y += (((z << 4) ^ (z >>> 5)) + z) ^ k30;
126: z += (((y >>> 5) ^ (y << 4)) + y) ^ k31;
127: out[off] = (byte) (y >> 24);
128: out[off + 1] = (byte) (y >> 16);
129: out[off + 2] = (byte) (y >> 8);
130: out[off + 3] = (byte) y;
131: out[off + 4] = (byte) (z >> 24);
132: out[off + 5] = (byte) (z >> 16);
133: out[off + 6] = (byte) (z >> 8);
134: out[off + 7] = (byte) z;
135: }
136:
137: public void decryptBlock(byte[] in, byte[] out, int off) {
138: int y = (in[off] << 24) | ((in[off + 1] & 255) << 16)
139: | ((in[off + 2] & 255) << 8) | (in[off + 3] & 255);
140: int z = (in[off + 4] << 24) | ((in[off + 5] & 255) << 16)
141: | ((in[off + 6] & 255) << 8) | (in[off + 7] & 255);
142: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k31;
143: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k30;
144: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k29;
145: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k28;
146: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k27;
147: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k26;
148: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k25;
149: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k24;
150: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k23;
151: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k22;
152: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k21;
153: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k20;
154: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k19;
155: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k18;
156: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k17;
157: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k16;
158: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k15;
159: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k14;
160: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k13;
161: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k12;
162: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k11;
163: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k10;
164: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k9;
165: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k8;
166: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k7;
167: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k6;
168: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k5;
169: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k4;
170: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k3;
171: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k2;
172: z -= (((y >>> 5) ^ (y << 4)) + y) ^ k1;
173: y -= (((z << 4) ^ (z >>> 5)) + z) ^ k0;
174: out[off] = (byte) (y >> 24);
175: out[off + 1] = (byte) (y >> 16);
176: out[off + 2] = (byte) (y >> 8);
177: out[off + 3] = (byte) y;
178: out[off + 4] = (byte) (z >> 24);
179: out[off + 5] = (byte) (z >> 16);
180: out[off + 6] = (byte) (z >> 8);
181: out[off + 7] = (byte) z;
182: }
183:
184: public int getKeyLength() {
185: return 16;
186: }
187:
188: }
|