]> hydra-www.ietfng.org Git - android-vcpass-oisafe/commitdiff
OI Safe: Include Trivium stream cipher from estreamJ.
authorpeli0101 <peli0101@72b678ce-9140-0410-bee8-679b907dd61a>
Sat, 28 Mar 2009 23:03:22 +0000 (23:03 +0000)
committerpeli0101 <peli0101@72b678ce-9140-0410-bee8-679b907dd61a>
Sat, 28 Mar 2009 23:03:22 +0000 (23:03 +0000)
git-svn-id: http://openintents.googlecode.com/svn/trunk/Safe@2006 72b678ce-9140-0410-bee8-679b907dd61a

src/estreamj/ciphers/trivium/Trivium.java [new file with mode: 0644]
src/estreamj/framework/ESJException.java [new file with mode: 0644]
src/estreamj/framework/Engine.java [new file with mode: 0644]
src/estreamj/framework/ICipher.java [new file with mode: 0644]
src/estreamj/framework/ICipherMaker.java [new file with mode: 0644]
src/estreamj/framework/Utils.java [new file with mode: 0644]

diff --git a/src/estreamj/ciphers/trivium/Trivium.java b/src/estreamj/ciphers/trivium/Trivium.java
new file mode 100644 (file)
index 0000000..9b7d1f1
--- /dev/null
@@ -0,0 +1,219 @@
+\r
+package estreamj.ciphers.trivium;\r
+\r
+import estreamj.framework.*;\r
+\r
+public class Trivium implements ICipher \r
+{\r
+       final static int KEY_SIZE_BITS = 80;\r
+       final static int IV_SIZE_BITS = 80;\r
+       \r
+       ///////////////////////////////////////////////////////////////////////////\r
+       \r
+       byte[] key = new byte[10];\r
+       int[] s = new int[10];\r
+       \r
+       ///////////////////////////////////////////////////////////////////////////\r
+       \r
+       public int getKeySize() \r
+       {\r
+               return KEY_SIZE_BITS >> 3;\r
+       }\r
+\r
+       public int getNonceSize() \r
+       {\r
+               return IV_SIZE_BITS >> 3;\r
+       }\r
+\r
+       public int getWordSize() \r
+       {\r
+               return 4;\r
+       }\r
+\r
+       public boolean isPatented() \r
+       {\r
+               return false;\r
+       }\r
+\r
+       public void process(\r
+                       byte[] inbuf, \r
+                       int inOfs, \r
+                       byte[] outbuf, \r
+                       int outOfs, \r
+                       int len) throws ESJException \r
+       {\r
+        int s11 = s[0];\r
+        int s12 = s[1];\r
+        int s13 = s[2];\r
+        int s21 = s[3];\r
+        int s22 = s[4];\r
+        int s23 = s[5];\r
+        int s31 = s[6];\r
+        int s32 = s[7];\r
+        int s33 = s[8];\r
+        int s34 = s[9];\r
+        \r
+        int outEnd = outOfs + (len & ~3); \r
+        \r
+        for (; outOfs < outEnd; outOfs+=4, inOfs+=4)\r
+        {\r
+               int t1, t2, t3, reg;\r
+               \r
+            t1 = ((s13 << 96-66) | (s12 >>> 66-64)) ^ ((s13 <<  96-93 ) | (s12 >>>  93-64)); \r
+            t2 = ((s23 << 96-69) | (s22 >>> 69-64)) ^ ((s23 <<  96-84 ) | (s22 >>>  84-64)); \r
+            t3 = ((s33 << 96-66) | (s32 >>> 66-64)) ^ ((s34 << 128-111) | (s33 >>> 111-96));\r
+            \r
+            reg = t1 ^ t2 ^ t3;\r
+            outbuf[outOfs    ] = (byte)(inbuf[inOfs    ] ^ reg); \r
+            outbuf[outOfs + 1] = (byte)(inbuf[inOfs + 1] ^ reg >> 8); \r
+            outbuf[outOfs + 2] = (byte)(inbuf[inOfs + 2] ^ reg >> 16); \r
+            outbuf[outOfs + 3] = (byte)(inbuf[inOfs + 3] ^ reg >> 24); \r
+\r
+            t1 ^= (((s13 <<  96-91 ) | (s12 >>>  91-64)) & ((s13 <<  96-92 ) | (s12 >>>  92-64))) ^ ((s23 << 96-78) | (s22 >>> 78-64)); \r
+            t2 ^= (((s23 <<  96-82 ) | (s22 >>>  82-64)) & ((s23 <<  96-83 ) | (s22 >>>  83-64))) ^ ((s33 << 96-87) | (s32 >>> 87-64)); \r
+            t3 ^= (((s34 << 128-109) | (s33 >>> 109-96)) & ((s34 << 128-110) | (s33 >>> 110-96))) ^ ((s13 << 96-69) | (s12 >>> 69-64)); \r
+            \r
+            s13 = s12; s12 = s11; s11 = t3;          \r
+            s23 = s22; s22 = s21; s21 = t1;          \r
+            s34 = s33; s33 = s32; s32 = s31; s31 = t2; \r
+        }\r
+        \r
+        // NOTE: could save some code memory by merging the two blocks, but that\r
+        // would decrease the speed because of additional conditional jumps...\r
+        outEnd = outOfs + (len & 3);\r
+        if (0 < outEnd)\r
+        {\r
+               int t1, t2, t3, reg;\r
+               \r
+            t1 = ((s13 << 96-66) | (s12 >>> 66-64)) ^ ((s13 <<  96-93 ) | (s12 >>>  93-64)); \r
+            t2 = ((s23 << 96-69) | (s22 >>> 69-64)) ^ ((s23 <<  96-84 ) | (s22 >>>  84-64)); \r
+            t3 = ((s33 << 96-66) | (s32 >>> 66-64)) ^ ((s34 << 128-111) | (s33 >>> 111-96));\r
+            \r
+            reg = t1 ^ t2 ^ t3;\r
+            for (;outOfs < outEnd; outOfs++, inOfs++)\r
+            {\r
+               outbuf[outOfs] = (byte)(inbuf[inOfs] ^ reg);\r
+               reg >>= 8;\r
+            }\r
+\r
+            t1 ^= (((s13 <<  96-91 ) | (s12 >>>  91-64)) & ((s13 <<  96-92 ) | (s12 >>>  92-64))) ^ ((s23 << 96-78) | (s22 >>> 78-64)); \r
+            t2 ^= (((s23 <<  96-82 ) | (s22 >>>  82-64)) & ((s23 <<  96-83 ) | (s22 >>>  83-64))) ^ ((s33 << 96-87) | (s32 >>> 87-64)); \r
+            t3 ^= (((s34 << 128-109) | (s33 >>> 109-96)) & ((s34 << 128-110) | (s33 >>> 110-96))) ^ ((s13 << 96-69) | (s12 >>> 69-64)); \r
+            \r
+            s13 = s12; s12 = s11; s11 = t3;          \r
+            s23 = s22; s22 = s21; s21 = t1;          \r
+            s34 = s33; s33 = s32; s32 = s31; s31 = t2; \r
+        }\r
+        \r
+        s[0] = s11;\r
+        s[1] = s12;\r
+        s[2] = s13;\r
+        s[3] = s21;\r
+        s[4] = s22;\r
+        s[5] = s23;\r
+        s[6] = s31;\r
+        s[7] = s32;\r
+        s[8] = s33;\r
+        s[9] = s34;\r
+       }\r
+\r
+       public void reset() throws ESJException \r
+       {\r
+               // key is cached already, nothing to do here\r
+       }\r
+\r
+       public void setupKey(\r
+                       int mode, \r
+                       byte[] key, \r
+                       int ofs) throws ESJException \r
+       {\r
+               System.arraycopy(key, ofs, this.key, 0, this.key.length);\r
+       }\r
+\r
+       public void setupNonce(\r
+                       byte[] nonce, \r
+                       int ofs) throws ESJException \r
+       {\r
+               byte[] key = this.key;\r
+               int[] s = this.s;\r
+               \r
+               int s11 = Utils.readInt32LE(key, 0);\r
+               int s12 = Utils.readInt32LE(key, 4);\r
+               int s13 = ( key[8]        & 0x0ff) | \r
+                         ((key[9] << 8)  & 0x0ff00); \r
+               int s21 = Utils.readInt32LE(nonce, ofs);\r
+               int s22 = Utils.readInt32LE(nonce, ofs + 4);\r
+               int s23 = ( nonce[ofs + 8]        & 0x0ff) | \r
+                     ((nonce[ofs + 9] << 8)  & 0x0ff00); \r
+               int s31 = 0;\r
+               int s32 = 0;\r
+               int s33 = 0;\r
+               int s34 = 0x07000;\r
+               \r
+\r
+               ///////////////!!!!!!!!!!!!!!!!!!!!!!!!\r
+//               System.out.printf(\r
+//                               "s11=%08x\n" +\r
+//                               "s12=%08x\n" +\r
+//                               "s13=%08x\n" +\r
+//                               "s21=%08x\n" +\r
+//                               "s22=%08x\n" +\r
+//                               "s23=%08x\n" +\r
+//                               "s31=%08x\n" +\r
+//                               "s32=%08x\n" +\r
+//                               "s33=%08x\n" +\r
+//                               "s34=%08x\n",\r
+//                                     s11, s12, s13,\r
+//                                     s21, s22, s23,\r
+//                                     s31, s32, s33, s34);            \r
+               \r
+        \r
+        for (int i = 0; i < 4*9; i++)\r
+        {\r
+               int t1, t2, t3;\r
+               \r
+            t1 = ((s13 << 96-66) | (s12 >>> 66-64)) ^ ((s13 <<  96-93 ) | (s12 >>>  93-64)); \r
+            t2 = ((s23 << 96-69) | (s22 >>> 69-64)) ^ ((s23 <<  96-84 ) | (s22 >>>  84-64)); \r
+            t3 = ((s33 << 96-66) | (s32 >>> 66-64)) ^ ((s34 << 128-111) | (s33 >>> 111-96)); \r
+\r
+            t1 ^= (((s13 <<  96-91 ) | (s12 >>>  91-64)) & ((s13 <<  96-92 ) | (s12 >>>  92-64))) ^ ((s23 << 96-78) | (s22 >>> 78-64)); \r
+            t2 ^= (((s23 <<  96-82 ) | (s22 >>>  82-64)) & ((s23 <<  96-83 ) | (s22 >>>  83-64))) ^ ((s33 << 96-87) | (s32 >>> 87-64)); \r
+            t3 ^= (((s34 << 128-109) | (s33 >>> 109-96)) & ((s34 << 128-110) | (s33 >>> 110-96))) ^ ((s13 << 96-69) | (s12 >>> 69-64)); \r
+            \r
+            s13 = s12; s12 = s11; s11 = t3;          \r
+            s23 = s22; s22 = s21; s21 = t1;          \r
+            s34 = s33; s33 = s32; s32 = s31; s31 = t2; \r
+        }\r
+        \r
+        s[0] = s11;\r
+        s[1] = s12;\r
+        s[2] = s13;\r
+        s[3] = s21;\r
+        s[4] = s22;\r
+        s[5] = s23;\r
+        s[6] = s31;\r
+        s[7] = s32;\r
+        s[8] = s33;\r
+        s[9] = s34;\r
+       }\r
+       \r
+    ///////////////////////////////////////////////////////////////////////////\r
+    \r
+    static class Maker implements ICipherMaker\r
+    {\r
+        public ICipher create() throws ESJException \r
+        {\r
+            return new Trivium();\r
+        }\r
+\r
+        public String getName() \r
+        {\r
+            return "Trivium";\r
+        }\r
+    }\r
+    \r
+    public static void register()\r
+    {\r
+        Engine.registerCipher(new Maker());\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/estreamj/framework/ESJException.java b/src/estreamj/framework/ESJException.java
new file mode 100644 (file)
index 0000000..45b3d7b
--- /dev/null
@@ -0,0 +1,23 @@
+\r
+package estreamj.framework;\r
+\r
+public class ESJException extends Exception \r
+{\r
+       private static final long serialVersionUID = 6375271013846829471L;\r
+\r
+       public ESJException() {\r
+               super();\r
+       }\r
+\r
+       public ESJException(String message) {\r
+               super(message);\r
+       }\r
+\r
+       public ESJException(Throwable cause) {\r
+               super(cause);\r
+       }\r
+\r
+       public ESJException(String message, Throwable cause) {\r
+               super(message, cause);\r
+       }\r
+}\r
diff --git a/src/estreamj/framework/Engine.java b/src/estreamj/framework/Engine.java
new file mode 100644 (file)
index 0000000..8d88859
--- /dev/null
@@ -0,0 +1,131 @@
+\r
+package estreamj.framework;\r
+\r
+import java.util.*;\r
+import java.lang.reflect.*;\r
+\r
+/**\r
+ * The engine accumulates all the stream ciphers available. All implementations\r
+ * register with the engine by themselves.\r
+ */\r
+public class Engine \r
+{\r
+       /**\r
+        * @return the names of all ciphers registered; can be empty if no ciphers\r
+        * have been registered so far\r
+        */\r
+       public static String[] getCipherNames()\r
+       {\r
+               String[] result;\r
+               \r
+               synchronized(_cphMks)\r
+               {\r
+                       Vector<String> lst = new Vector<String>();\r
+                       lst.addAll(_cphMks.keySet());\r
+                       Collections.sort(lst);\r
+                       result = lst.toArray(new String[lst.size()]);\r
+               }\r
+               \r
+               return result;\r
+       }\r
+       \r
+       /**\r
+        * Creates a new cipher instance.\r
+        * @param name name of the cipher to make\r
+        * @return new cipher instance\r
+        * @throws ESJException if any error occured\r
+        */\r
+       public static ICipher createCipher(String name) throws ESJException\r
+       {\r
+               ICipherMaker maker;\r
+               \r
+               synchronized(_cphMks)\r
+               {\r
+                       maker = _cphMks.get(name);\r
+                       if (null == maker)\r
+                       {\r
+                               throw new ESJException("no maker registered for cipher \"" + \r
+                                               name + "\"");\r
+                       }\r
+               }\r
+               return maker.create();\r
+       }\r
+       \r
+       ///////////////////////////////////////////////////////////////////////////\r
+\r
+       static HashMap<String, ICipherMaker> _cphMks = \r
+               new HashMap<String, ICipherMaker>();\r
+\r
+       /**\r
+        * Called by cipher implementations to register their factories, usually\r
+        * during startup time.\r
+        * @param cphMk the factory to register\r
+        */\r
+       public static void registerCipher(ICipherMaker cphMk)\r
+       {\r
+               String name = cphMk.getName();\r
+       \r
+               synchronized(_cphMks)\r
+               {\r
+                       if (_cphMks.containsKey(name))\r
+                       {\r
+                               System.err.println("cipher \"" + name +\r
+                                               "\" has been registered already");\r
+                               System.exit(1);\r
+                       }\r
+                       _cphMks.put(cphMk.getName(), cphMk);\r
+               }\r
+       }\r
+\r
+       ///////////////////////////////////////////////////////////////////////////\r
+       \r
+       // all the cipher classes must be listed here, the rest of the registration\r
+       // is done via reflection; this is done by having every class implementing\r
+       // a 'public static void register()' method (see below)\r
+       static Class[] _cipherClasses =\r
+       {\r
+               //estreamj.ciphers.phelix.Phelix.class,\r
+               //estreamj.ciphers.hc256.HC256.class,\r
+               //estreamj.ciphers.salsa20.Salsa20.class,\r
+               //estreamj.ciphers.aes.AESCTR.class,\r
+               //estreamj.ciphers.mickey.MICKEY.class,\r
+               //estreamj.ciphers.mickey.MICKEY128.class,\r
+               //estreamj.ciphers.hermes8.Hermes8.class,\r
+               //estreamj.ciphers.rc4.RC4.class,\r
+               //estreamj.ciphers.dragon.Dragon.class,\r
+               //estreamj.ciphers.lex.LEX.class,\r
+               estreamj.ciphers.trivium.Trivium.class//,\r
+               //estreamj.ciphers.sosemanuk.Sosemanuk.class,\r
+               //estreamj.ciphers.grain.GrainP2.class,\r
+               //estreamj.ciphers.grain.Grain128.class,\r
+               //estreamj.ciphers.nil.Nil.class\r
+       };\r
+\r
+       ///////////////////////////////////////////////////////////////////////////\r
+       \r
+       static\r
+       {\r
+               try\r
+               {\r
+                       for (int i = 0; i < _cipherClasses.length; i++)\r
+                       {\r
+                               // check if the register method is there and static\r
+                               Class cls = _cipherClasses[i];\r
+                               Method mthd = cls.getMethod("register", (Class[])null);\r
+                               if (Modifier.STATIC != (mthd.getModifiers() & Modifier.STATIC))\r
+                               {\r
+                                       throw new Exception(\r
+                                                       "register() method is not static (" + cls + ")");\r
+                               }\r
+                               // ready to register\r
+                               mthd.invoke(null, (Object[])null);\r
+                       }\r
+               }\r
+               catch (Exception e)\r
+               {\r
+                       System.err.println(\r
+                                       "cipher registration error (" + e.getMessage() + ")");\r
+                       System.exit(1);\r
+               }\r
+       }\r
+}\r
diff --git a/src/estreamj/framework/ICipher.java b/src/estreamj/framework/ICipher.java
new file mode 100644 (file)
index 0000000..10a6cfe
--- /dev/null
@@ -0,0 +1,91 @@
+\r
+package estreamj.framework;\r
+\r
+/**\r
+ * Generic interface every cipher needs to implement, so it can participate in\r
+ * the test framework. If a cipher comes in different flavors (variable key\r
+ * sizes, MAC computation or not, etc.) it should then implement a version for\r
+ * each of them - this keeps the actual testing logic simple. Simple is good.\r
+ */\r
+public interface ICipher \r
+{\r
+       /**\r
+        * mode: instance is used for encryption\r
+        */\r
+       public final static int MODE_ENCRYPT = 0;\r
+\r
+       /**\r
+        * mode: instance is used for decryption\r
+        */\r
+       public final static int MODE_DECRYPT = 1;\r
+       \r
+       ///////////////////////////////////////////////////////////////////////////\r
+       \r
+       /**\r
+        * @return true: algorithm is patented, check with vendor for license\r
+        * details / false: free to use in private and commerical applications \r
+        */\r
+       public boolean isPatented();\r
+       \r
+       /**\r
+        * @return key size in bytes\r
+        */\r
+       public int getKeySize();\r
+       \r
+       /**\r
+        * @return nonce size in bytes.\r
+        */\r
+       public int getNonceSize();\r
+       \r
+       /**\r
+        * @return alignment of data needed during calls into process() \r
+        */\r
+       public int getWordSize();\r
+\r
+       ///////////////////////////////////////////////////////////////////////////\r
+\r
+       /**\r
+        * Resets the instance, so it can be reused.\r
+        * @exception ESJException if any error occurs\r
+        */\r
+       public void reset() throws ESJException;\r
+       \r
+       /**\r
+        * Sets up a new key with the existing instance. \r
+        * @param mode see MODE_xxx\r
+        * @param key buffer with key material\r
+        * @param ofs where the key starts \r
+        * @exception ESJException if any error occurs\r
+        */\r
+       public void setupKey(int mode, byte[] key, int ofs) \r
+               throws ESJException;\r
+                       \r
+       /**\r
+        * Sets up a new nonce with the existing cipher instance. \r
+        * @param mode see MODE_xxx\r
+        * @param nonce buffer with nonce material\r
+        * @param ofs where the nonce starts\r
+        * @exception ESJException if any error occurs\r
+        */\r
+       public void setupNonce(byte[] nonce, int ofs) \r
+               throws ESJException;\r
+       \r
+       ///////////////////////////////////////////////////////////////////////////\r
+       \r
+       /**\r
+        * Processes data.\r
+        * @param inbuf input buffer\r
+        * @param inOfs where to start reading from the input buffer\r
+        * @param outbuf output buffer\r
+        * @param outOfs where to start writing in the output buffer\r
+        * @param len number of bytes to process, must be aligned to the cipher's\r
+        * word size except on the last call where an arbitrary size can be used\r
+        * @throws ESJException in any error occured\r
+        */\r
+       public void process(\r
+                       byte[] inbuf, \r
+                       int inOfs, \r
+                       byte[] outbuf, \r
+                       int outOfs, \r
+                       int len) throws ESJException;\r
+}\r
diff --git a/src/estreamj/framework/ICipherMaker.java b/src/estreamj/framework/ICipherMaker.java
new file mode 100644 (file)
index 0000000..ffaa867
--- /dev/null
@@ -0,0 +1,22 @@
+\r
+package estreamj.framework;\r
+\r
+/**\r
+ * Simple cipher factory.\r
+ */\r
+public interface ICipherMaker \r
+{\r
+       /**\r
+        * @return the name of cipher, which is used for queries - so it must be\r
+        * unique\r
+        */\r
+       public String getName();\r
+       \r
+       /**\r
+        * Create a new cipher instance.\r
+        * @return new instance, which can also be of the type ICipherMAC, use the\r
+        * "instanceof" keyword to find out what you are dealing with \r
+        * @throws ESJException if any error occured\r
+        */\r
+       public ICipher create() throws ESJException;\r
+}\r
diff --git a/src/estreamj/framework/Utils.java b/src/estreamj/framework/Utils.java
new file mode 100644 (file)
index 0000000..97f9336
--- /dev/null
@@ -0,0 +1,230 @@
+\r
+package estreamj.framework;\r
+\r
+import java.io.*;\r
+import java.util.Arrays;\r
+\r
+public class Utils \r
+{\r
+       public static void fillPattern123(byte[] buf, int ofs, int len)\r
+       {\r
+               int counter, end;\r
+               \r
+               counter = 0;\r
+               end = ofs + len;\r
+               while (ofs < end)\r
+               {\r
+                       buf[ofs++] = (byte)counter++;\r
+               }\r
+       }\r
+\r
+       public static boolean checkPattern123(byte[] buf, int ofs, int len)\r
+       {\r
+               int counter, end;\r
+               \r
+               counter = 0;\r
+               end = ofs + len;\r
+               while (ofs < end)\r
+               {\r
+                       if (buf[ofs] != (byte)counter)\r
+                       {\r
+                               return false;\r
+                       }\r
+                       counter++;\r
+                       ofs++;\r
+               }\r
+               return true;\r
+       }\r
+       \r
+    public static byte[] makeOutputBuffer(int len, int extraLen)\r
+    {\r
+        byte[] result = new byte[len + extraLen];\r
+        Arrays.fill(result, (byte)0xcc);\r
+        return result;\r
+    }\r
+    \r
+    public static boolean arraysEquals(\r
+               byte[] a, int ofsA, byte[] b, int ofsB, int len)\r
+       {\r
+       int end = ofsA + len;\r
+       while (ofsA < end)\r
+       {\r
+               if (b[ofsB++] != a[ofsA++])\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+       return true;\r
+       }\r
+    \r
+    public final static int readInt32LE(byte[] data, int ofs)\r
+    {\r
+       return ( data[ofs + 3]         << 24) |\r
+                  ((data[ofs + 2] & 0xff) << 16) |\r
+                  ((data[ofs + 1] & 0xff) <<  8) |\r
+                   (data[ofs    ] & 0xff);\r
+    }\r
+    \r
+    public final static void writeInt32LE(int value, byte[] data, int ofs)\r
+    {\r
+       data[ofs    ] = (byte)(value       );\r
+       data[ofs + 1] = (byte)(value >>>  8);\r
+       data[ofs + 2] = (byte)(value >>> 16);\r
+       data[ofs + 3] = (byte)(value >>> 24);\r
+    }\r
+\r
+    public final static int readInt32BE(byte[] data, int ofs)\r
+    {\r
+       return ( data[ofs    ]         << 24) |\r
+                  ((data[ofs + 1] & 0xff) << 16) |\r
+                  ((data[ofs + 2] & 0xff) <<  8) |\r
+                   (data[ofs + 3] & 0xff);\r
+    }\r
+    \r
+    public final static void writeInt32BE(int value, byte[] data, int ofs)\r
+    {\r
+       data[ofs + 3] = (byte)(value       );\r
+       data[ofs + 2] = (byte)(value >>>  8);\r
+       data[ofs + 1] = (byte)(value >>> 16);\r
+       data[ofs    ] = (byte)(value >>> 24);\r
+    }\r
+    \r
+    public static byte[] hexStrToBytes(String hex)\r
+    {\r
+       int len = hex.length();\r
+       if (1 == (len & 1))\r
+       {\r
+               return null;\r
+       }\r
+       byte[] result = new byte[len >> 1];\r
+       int r = 0;\r
+       int pos = 0;\r
+       while (pos < len)\r
+       {\r
+               int nReg = 0;\r
+               for (int nI = 0; nI < 2; nI++)\r
+               {\r
+                       nReg <<= 4;\r
+                       char c = Character.toLowerCase(hex.charAt(pos++));\r
+                       if ('0' <= c && '9' >= c)\r
+                       {\r
+                               nReg |= c - '0';\r
+                       }\r
+                       else if ('a' <= c && 'f' >= c)\r
+                       {\r
+                               nReg |= (c - 'a') + 10;\r
+                       }\r
+                       else\r
+                       {\r
+                               return null;\r
+                       }\r
+               }\r
+                       result[r++] = (byte)nReg;\r
+       }\r
+       return result;\r
+    }\r
+    \r
+       final static char[] HEXTAB =\r
+       {\r
+               '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'\r
+       };\r
+\r
+       public static int hexDump(\r
+               InputStream is,\r
+               PrintStream ps,\r
+               int maxRead,\r
+               int bytesPerLine)\r
+       {\r
+               int read, chr, i, result;\r
+               char[] pad;\r
+               StringBuffer left, right;\r
+               \r
+               \r
+               if (1 > bytesPerLine)\r
+               {\r
+                       bytesPerLine = 1;\r
+               }\r
+               \r
+               left = new StringBuffer();\r
+               right = new StringBuffer();\r
+               \r
+               result = 0;\r
+               \r
+               for (read = 0, i = 0;;)\r
+               {\r
+                       if (-1 != maxRead)\r
+                       {\r
+                               if (maxRead <= read)\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+       \r
+                       try\r
+                       {\r
+                               if (-1 == (chr = is.read()))\r
+                               {\r
+                                       break;  \r
+                               }\r
+                       }\r
+                       catch (IOException ioe)\r
+                       {\r
+                               break;\r
+                       }\r
+                       \r
+                       result++;\r
+\r
+                       if (0 < i++)\r
+                       {\r
+                               left.append(' ');\r
+                       }\r
+\r
+                       left.append(HEXTAB[chr >>> 4]);\r
+                       left.append(HEXTAB[chr & 0x0f]);\r
+\r
+                       right.append((chr < ' ') ? '.' : (char)chr);\r
+                       \r
+                       if (0 == (i % bytesPerLine))\r
+                       {\r
+                               ps.print(left.toString());\r
+                               ps.print("    ");\r
+                               ps.println(right.toString());\r
+                               \r
+                               left.setLength(0);\r
+                               right.setLength(0);\r
+                               \r
+                               i = 0;\r
+                       }\r
+               }\r
+\r
+               if (0 < i)\r
+               {\r
+                       pad = new char[((bytesPerLine - i) * 3) + 4];\r
+                       Arrays.fill(pad, ' ');  \r
+               \r
+                       ps.print(left.toString());\r
+                       ps.print(pad);\r
+                       ps.println(right.toString());\r
+               }\r
+               \r
+               return result;\r
+       }\r
+       \r
+    public static byte[] swapByteOrder32(byte[] data, int ofs, int len)\r
+    {\r
+       int end = ofs + len;\r
+       byte tmp;\r
+       \r
+       for (; ofs < end; ofs += 4)\r
+       {\r
+               tmp = data[ofs];\r
+               data[ofs] = data[ofs + 3];\r
+               data[ofs + 3] = tmp;\r
+\r
+               tmp = data[ofs + 1];\r
+               data[ofs + 1] = data[ofs + 2];\r
+               data[ofs + 2] = tmp;\r
+       }\r
+       return data;\r
+    }\r
+}\r