classpathx-crypto
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Classpathx-crypto] [patch] Serpent cipher


From: Casey Marshall
Subject: [Classpathx-crypto] [patch] Serpent cipher
Date: Tue, 4 Jun 2002 17:15:08 -0700 (PDT)

Hello,

I've been doing some studying in cryptography, came across GNU classpathx,
and have been working on implementing some ciphers using the crypto API.

The patch which follows (which is longish, but I didn't want to do an
attachment---please admonish if this is poor etiquette) is an
implementation of Serpent which appears correct in a few tests. It does
not, as far as I know, refer to any non-free techniques---is uses some
optimized S-box functions found by Dag Arne Osvik which are implemented
in a GPL'd ADA implementation from http://www.ii.uib.no/~gisle/serpent.html.

The patch is based on a recent CVS checkout and updates the gcj
Makefile.{in,am}, the classes Registry and CipherFactory, and adds the
Serpent class itself. Classpathx is welcome to use it.

Cheers,

-- 
Casey Marshall < address@hidden > http://metastatic.org/

=== cut here ===
diff -Naurw crypto/gcj/source/Makefile.am crypto.1/gcj/source/Makefile.am
--- crypto/gcj/source/Makefile.am       Wed May 29 02:02:35 2002
+++ crypto.1/gcj/source/Makefile.am     Tue Jun  4 16:04:52 2002
@@ -86,6 +86,7 @@
  gnu/crypto/cipher/Khazad.java \
  gnu/crypto/cipher/NullCipher.java \
  gnu/crypto/cipher/Rijndael.java \
+ gnu/crypto/cipher/Serpent.java \
  gnu/crypto/cipher/Square.java \
  gnu/crypto/cipher/Twofish.java \
  gnu/crypto/hash/BaseHash.java \
diff -Naurw crypto/gcj/source/Makefile.in crypto.1/gcj/source/Makefile.in
--- crypto/gcj/source/Makefile.in       Wed May 29 02:02:35 2002
+++ crypto.1/gcj/source/Makefile.in     Tue Jun  4 16:05:44 2002
@@ -203,6 +176,7 @@
  gnu/crypto/cipher/Khazad.java \
  gnu/crypto/cipher/NullCipher.java \
  gnu/crypto/cipher/Rijndael.java \
+ gnu/crypto/cipher/Serpent.java \
  gnu/crypto/cipher/Square.java \
  gnu/crypto/cipher/Twofish.java \
  gnu/crypto/hash/BaseHash.java \
@@ -297,9 +271,9 @@
        gnu/crypto/cipher/IBlockCipher.lo \
        gnu/crypto/cipher/IBlockCipherSpi.lo \
        gnu/crypto/cipher/Khazad.lo gnu/crypto/cipher/NullCipher.lo \
-       gnu/crypto/cipher/Rijndael.lo gnu/crypto/cipher/Square.lo \
-       gnu/crypto/cipher/Twofish.lo gnu/crypto/hash/BaseHash.lo \
-       gnu/crypto/hash/HashFactory.lo \
+       gnu/crypto/cipher/Rijndael.lo gnu/crypto/cipher/Serpent.lo \
+       gnu/crypto/cipher/Square.lo gnu/crypto/cipher/Twofish.lo \
+       gnu/crypto/hash/BaseHash.lo gnu/crypto/hash/HashFactory.lo \
        gnu/crypto/hash/IMessageDigest.lo gnu/crypto/hash/MD5.lo \
        gnu/crypto/hash/RipeMD128.lo gnu/crypto/hash/RipeMD160.lo \
        gnu/crypto/hash/Sha160.lo gnu/crypto/hash/Whirlpool.lo \
@@ -388,6 +366,7 @@
 @AMDEP_TRUE@   gnu/crypto/cipher/$(DEPDIR)/Khazad.Plo \
 @AMDEP_TRUE@   gnu/crypto/cipher/$(DEPDIR)/NullCipher.Plo \
 @AMDEP_TRUE@   gnu/crypto/cipher/$(DEPDIR)/Rijndael.Plo \
address@hidden@ gnu/crypto/cipher/$(DEPDIR)/Serpent.Plo \
 @AMDEP_TRUE@   gnu/crypto/cipher/$(DEPDIR)/Square.Plo \
 @AMDEP_TRUE@   gnu/crypto/cipher/$(DEPDIR)/Twofish.Plo \
 @AMDEP_TRUE@   gnu/crypto/hash/$(DEPDIR)/BaseHash.Plo \
@@ -561,6 +534,9 @@
 gnu/crypto/cipher/Rijndael.lo: gnu/crypto/cipher/Rijndael.java \
        gnu/crypto/cipher/.dirstamp \
        gnu/crypto/cipher/$(DEPDIR)/.dirstamp
+gnu/crypto/cipher/Serpent.lo: gnu/crypto/cipher/Serpent.java \
+       gnu/crypto/cipher/.dirstamp \
+       gnu/crypto/cipher/$(DEPDIR)/.dirstamp
 gnu/crypto/cipher/Square.lo: gnu/crypto/cipher/Square.java \
        gnu/crypto/cipher/.dirstamp \
        gnu/crypto/cipher/$(DEPDIR)/.dirstamp
@@ -880,6 +852,8 @@
        -rm -f gnu/crypto/cipher/NullCipher.lo
        -rm -f gnu/crypto/cipher/Rijndael.$(OBJEXT)
        -rm -f gnu/crypto/cipher/Rijndael.lo
+       -rm -f gnu/crypto/cipher/Serpent.$(OBJEXT)
+       -rm -f gnu/crypto/cipher/Serpent.lo
        -rm -f gnu/crypto/cipher/Square.$(OBJEXT)
        -rm -f gnu/crypto/cipher/Square.lo
        -rm -f gnu/crypto/cipher/Twofish.$(OBJEXT)
@@ -1075,6 +1049,7 @@
 @AMDEP_TRUE@@am__include@ 
@address@hidden/crypto/cipher/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ 
@address@hidden/crypto/cipher/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ 
@address@hidden/crypto/cipher/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ 
@address@hidden/crypto/cipher/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ 
@address@hidden/crypto/cipher/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ 
@address@hidden/crypto/cipher/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/crypto/hash/$(DEPDIR)/address@hidden@
@@ -1340,6 +1315,24 @@
 @AMDEP_TRUE@   $(GCJDEPMODE) $(depcomp) @AMDEPBACKSLASH@
        $(LIBTOOL) --mode=compile $(GCJ) $(AM_GCJFLAGS) $(GCJFLAGS) -c -o 
gnu/crypto/cipher/Rijndael.lo `test -f 'gnu/crypto/cipher/Rijndael.java' || 
echo '$(srcdir)/'`gnu/crypto/cipher/Rijndael.java

+gnu/crypto/cipher/Serpent.o: gnu/crypto/cipher/Serpent.java
address@hidden@ source='gnu/crypto/cipher/Serpent.java' 
object='gnu/crypto/cipher/Serpent.o' libtool=no @AMDEPBACKSLASH@
address@hidden@ depfile='gnu/crypto/cipher/$(DEPDIR)/Serpent.Po' 
tmpdepfile='gnu/crypto/cipher/$(DEPDIR)/Serpent.TPo' @AMDEPBACKSLASH@
address@hidden@ $(GCJDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(GCJ) $(AM_GCJFLAGS) $(GCJFLAGS) -c -o gnu/crypto/cipher/Serpent.o 
`test -f 'gnu/crypto/cipher/Serpent.java' || echo 
'$(srcdir)/'`gnu/crypto/cipher/Serpent.java
+
+gnu/crypto/cipher/Serpent.obj: gnu/crypto/cipher/Serpent.java
address@hidden@ source='gnu/crypto/cipher/Serpent.java' 
object='gnu/crypto/cipher/Serpent.obj' libtool=no @AMDEPBACKSLASH@
address@hidden@ depfile='gnu/crypto/cipher/$(DEPDIR)/Serpent.Po' 
tmpdepfile='gnu/crypto/cipher/$(DEPDIR)/Serpent.TPo' @AMDEPBACKSLASH@
address@hidden@ $(GCJDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(GCJ) $(AM_GCJFLAGS) $(GCJFLAGS) -c -o gnu/crypto/cipher/Serpent.obj 
`cygpath -w gnu/crypto/cipher/Serpent.java`
+
+gnu/crypto/cipher/Serpent.lo: gnu/crypto/cipher/Serpent.java
address@hidden@ source='gnu/crypto/cipher/Serpent.java' 
object='gnu/crypto/cipher/Serpent.lo' libtool=yes @AMDEPBACKSLASH@
address@hidden@ depfile='gnu/crypto/cipher/$(DEPDIR)/Serpent.Plo' 
tmpdepfile='gnu/crypto/cipher/$(DEPDIR)/Serpent.TPlo' @AMDEPBACKSLASH@
address@hidden@ $(GCJDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LIBTOOL) --mode=compile $(GCJ) $(AM_GCJFLAGS) $(GCJFLAGS) -c -o 
gnu/crypto/cipher/Serpent.lo `test -f 'gnu/crypto/cipher/Serpent.java' || echo 
'$(srcdir)/'`gnu/crypto/cipher/Serpent.java
+
 gnu/crypto/cipher/Square.o: gnu/crypto/cipher/Square.java
 @AMDEP_TRUE@   source='gnu/crypto/cipher/Square.java' 
object='gnu/crypto/cipher/Square.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@   depfile='gnu/crypto/cipher/$(DEPDIR)/Square.Po' 
tmpdepfile='gnu/crypto/cipher/$(DEPDIR)/Square.TPo' @AMDEPBACKSLASH@
diff -Naurw crypto/source/gnu/crypto/Registry.java 
crypto.1/source/gnu/crypto/Registry.java
--- crypto/source/gnu/crypto/Registry.java      Fri Jan 11 13:58:27 2002
+++ crypto.1/source/gnu/crypto/Registry.java    Tue Jun  4 16:24:53 2002
@@ -45,6 +45,7 @@
    String ANUBIS_CIPHER =   "anubis";
    String KHAZAD_CIPHER =   "khazad";
    String RIJNDAEL_CIPHER = "rijndael";
+   String SERPENT_CIPHER =  "serpent";
    String SQUARE_CIPHER =   "square";
    String TWOFISH_CIPHER =  "twofish";
    String NULL_CIPHER =     "null";
diff -Naurw crypto/source/gnu/crypto/cipher/CipherFactory.java 
crypto.1/source/gnu/crypto/cipher/CipherFactory.java
--- crypto/source/gnu/crypto/cipher/CipherFactory.java  Fri Jan 11 13:57:28 2002
+++ crypto.1/source/gnu/crypto/cipher/CipherFactory.java        Tue Jun  4 
16:18:25 2002
@@ -82,6 +82,8 @@
       } else if (name.equalsIgnoreCase(RIJNDAEL_CIPHER)
               || name.equalsIgnoreCase(AES_CIPHER)) {
          result = new Rijndael();
+      } else if (name.equalsIgnoreCase(SERPENT_CIPHER)) {
+         result = new Serpent();
       } else if (name.equalsIgnoreCase(SQUARE_CIPHER)) {
          result = new Square();
       } else if (name.equalsIgnoreCase(TWOFISH_CIPHER)) {
@@ -108,6 +110,7 @@
       hs.add(ANUBIS_CIPHER);
       hs.add(KHAZAD_CIPHER);
       hs.add(RIJNDAEL_CIPHER);
+      hs.add(SERPENT_CIPHER);
       hs.add(SQUARE_CIPHER);
       hs.add(TWOFISH_CIPHER);
       hs.add(NULL_CIPHER);
diff -Naurw crypto/source/gnu/crypto/cipher/Serpent.java 
crypto.1/source/gnu/crypto/cipher/Serpent.java
--- crypto/source/gnu/crypto/cipher/Serpent.java        Wed Dec 31 16:00:00 1969
+++ crypto.1/source/gnu/crypto/cipher/Serpent.java      Tue Jun  4 14:21:54 2002
@@ -0,0 +1,740 @@
+package gnu.crypto.cipher;
+
+// ----------------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; see the file COPYING.  If not, write to the
+//
+//    Free Software Foundation Inc.,
+//    59 Temple Place - Suite 330,
+//    Boston, MA 02111-1307
+//    USA
+//
+// As a special exception, if you link this library with other files to produce
+// an executable, this library does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This exception
+// does not however invalidate any other reasons why the executable file might
+// be covered by the GNU General Public License.
+// ----------------------------------------------------------------------------
+
+import gnu.crypto.Registry;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.security.InvalidKeyException;
+
+/**
+ * Serpent is a 32-round substitution-permutation network block cipher,
+ * operating on 128-bit blocks and accepting keys of 128, 192, and 256
+ * bits in length. At each round the plaintext is XORed with a 128 bit
+ * portion of the session key -- a 4224 bit key computed from the input
+ * key -- then one of eight S-boxes are applied, and finally a simple
+ * linear transformation is done. Decryption does the exact same thing
+ * in reverse order, and using the eight inverses of the S-boxes.
+ * <p>
+ * Serpent was designed by Ross Anderson, Eli Biham, and Lars Knudsen as
+ * a proposed cipher for the Advanced Encryption Standard.
+ * <p>
+ * Reference: <a
+ * href="http://www.cl.cam.ac.uk/~rja14/serpent.html";>Serpent: A
+ * Candidate Block Cipher for the Advanced Encryption Standard.</a>
+ * <p>
+ * Serpent can be sped up greatly by replacing S-box substitution with a
+ * sequence of binary operations, and the optimal implementation depends
+ * upon finding the fastest sequence of binary operations that reproduce
+ * this substitution. This implementation uses the S-boxes discovered by
+ * <a href="http://www.ii.uib.no/~osvik/";>Dag Arne Osvik</a>, which are
+ * optimized for the Pentium family of processors.
+ *
+ * @version $Revision$
+ */
+public class Serpent extends BaseCipher {
+
+ // Constants and variables
+   // -----------------------------------------------------------------
+
+   private static final String NAME = "serpent";
+
+   private static final int DEFAULT_KEY_SIZE = 32;
+   private static final int DEFAULT_BLOCK_SIZE = 16;
+   private static final int ROUNDS = 32;
+
+   /** The fractional part of the golden ratio, (sqrt(5)+1)/2. */
+   private static final int PHI = 0x9e3779b9;
+
+   // Constructors
+   // -----------------------------------------------------------------
+
+   /** Trivial zero-argument constructor. */
+   public Serpent() {
+      super(Registry.SERPENT_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
+   }
+
+   // Implementation of the Cloneable interface
+   // -----------------------------------------------------------------
+
+   public Object clone() {
+      return new Serpent();
+   }
+
+ // Implementations of abstract methods from BaseCipher
+   // -----------------------------------------------------------------
+
+   public Iterator blockSizes() {
+      return Collections.singleton(new Integer(DEFAULT_BLOCK_SIZE)).iterator();
+   }
+
+   public Iterator keySizes() {
+      return new Iterator() {
+         int i = 0;
+         // Support 128, 192, and 256 bit keys.
+         Integer[] keySizes = {
+            new Integer(16), new Integer(24), new Integer(32)
+         };
+
+         public boolean hasNext() {
+            return i < keySizes.length;
+         }
+
+         public Object next() {
+            if (hasNext()) {
+               return keySizes[i++];
+            }
+            return null;
+         }
+
+         public void remove() {
+            throw new UnsupportedOperationException();
+         }
+      };
+   }
+
+   public Object
+   makeKey(byte[] key, int blockSize) throws InvalidKeyException {
+      // Not strictly true, but here to conform with the AES proposal.
+      // This restriction can be removed if deemed necessary.
+      if (key.length != 16 && key.length != 24 && key.length != 32) {
+         throw new InvalidKeyException("Key length is not 16, 24, or 32 
bytes");
+      }
+
+      // Here w is our "pre-key".
+      int[] w = new int[4*(ROUNDS+1)];
+      int i, j;
+      for (i = 0, j = key.length-4; i < 8 && j >= 0; i++) {
+         w[i] = (key[j  ] & 0xff) << 24 | (key[j+1] & 0xff) << 16 |
+                (key[j+2] & 0xff) << 8  | (key[j+3] & 0xff);
+         j -= 4;
+      }
+      // Pad key if < 256 bits.
+      if (i != 8) {
+         w[i] = 1;
+      }
+      // Transform using w_i-8 ... w_i-1
+      for (i = 8; i < 16; i++) {
+         int t = w[i-8] ^ w[i-5] ^ w[i-3] ^ w[i-1] ^ PHI ^ (i-8);
+         w[i] = t << 11 | t >>> 21;
+      }
+      // Translate by 8.
+      for (i = 0; i < 8; i++) {
+         w[i] = w[i+8];
+      }
+      // Transform the rest of the key.
+      for (i = 8; i < w.length; i++) {
+         int t = w[i-8] ^ w[i-5] ^ w[i-3] ^ w[i-1] ^ PHI ^ i;
+         w[i] = t << 11 | t >>> 21;
+      }
+
+      // After these s-boxes the pre-key (w, above) will become the
+      // session key (w, below).
+      sbox3(w[  0], w[  1], w[  2], w[  3], w,   0);
+      sbox2(w[  4], w[  5], w[  6], w[  7], w,   4);
+      sbox1(w[  8], w[  9], w[ 10], w[ 11], w,   8);
+      sbox0(w[ 12], w[ 13], w[ 14], w[ 15], w,  12);
+      sbox7(w[ 16], w[ 17], w[ 18], w[ 19], w,  16);
+      sbox6(w[ 20], w[ 21], w[ 22], w[ 23], w,  20);
+      sbox5(w[ 24], w[ 25], w[ 26], w[ 27], w,  24);
+      sbox4(w[ 28], w[ 29], w[ 30], w[ 31], w,  28);
+      sbox3(w[ 32], w[ 33], w[ 34], w[ 35], w,  32);
+      sbox2(w[ 36], w[ 37], w[ 38], w[ 39], w,  36);
+      sbox1(w[ 40], w[ 41], w[ 42], w[ 43], w,  40);
+      sbox0(w[ 44], w[ 45], w[ 46], w[ 47], w,  44);
+      sbox7(w[ 48], w[ 49], w[ 50], w[ 51], w,  48);
+      sbox6(w[ 52], w[ 53], w[ 54], w[ 55], w,  52);
+      sbox5(w[ 56], w[ 57], w[ 58], w[ 59], w,  56);
+      sbox4(w[ 60], w[ 61], w[ 62], w[ 63], w,  60);
+      sbox3(w[ 64], w[ 65], w[ 66], w[ 67], w,  64);
+      sbox2(w[ 68], w[ 69], w[ 70], w[ 71], w,  68);
+      sbox1(w[ 72], w[ 73], w[ 74], w[ 75], w,  72);
+      sbox0(w[ 76], w[ 77], w[ 78], w[ 79], w,  76);
+      sbox7(w[ 80], w[ 81], w[ 82], w[ 83], w,  80);
+      sbox6(w[ 84], w[ 85], w[ 86], w[ 87], w,  84);
+      sbox5(w[ 88], w[ 89], w[ 90], w[ 91], w,  88);
+      sbox4(w[ 92], w[ 93], w[ 94], w[ 95], w,  92);
+      sbox3(w[ 96], w[ 97], w[ 98], w[ 99], w,  96);
+      sbox2(w[100], w[101], w[102], w[103], w, 100);
+      sbox1(w[104], w[105], w[106], w[107], w, 104);
+      sbox0(w[108], w[109], w[110], w[111], w, 108);
+      sbox7(w[112], w[113], w[114], w[115], w, 112);
+      sbox6(w[116], w[117], w[118], w[119], w, 116);
+      sbox5(w[120], w[121], w[122], w[123], w, 120);
+      sbox4(w[124], w[125], w[126], w[127], w, 124);
+      sbox3(w[128], w[129], w[130], w[131], w, 128);
+
+      return w;
+   }
+
+   public
+   void encrypt(byte[] in, int i, byte[] out, int o, Object K, int bs) {
+      int[] key = (int[]) K;
+      int[] x = new int[4];
+      x[3] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+      x[2] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+      x[1] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+      x[0] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+
+      sbox0(key[  0]^x[0], key[  1]^x[1], key[  2]^x[2], key[  3]^x[3], x, 0);
+      transform(x);
+      sbox1(key[  4]^x[0], key[  5]^x[1], key[  6]^x[2], key[  7]^x[3], x, 0);
+      transform(x);
+      sbox2(key[  8]^x[0], key[  9]^x[1], key[ 10]^x[2], key[ 11]^x[3], x, 0);
+      transform(x);
+      sbox3(key[ 12]^x[0], key[ 13]^x[1], key[ 14]^x[2], key[ 15]^x[3], x, 0);
+      transform(x);
+      sbox4(key[ 16]^x[0], key[ 17]^x[1], key[ 18]^x[2], key[ 19]^x[3], x, 0);
+      transform(x);
+      sbox5(key[ 20]^x[0], key[ 21]^x[1], key[ 22]^x[2], key[ 23]^x[3], x, 0);
+      transform(x);
+      sbox6(key[ 24]^x[0], key[ 25]^x[1], key[ 26]^x[2], key[ 27]^x[3], x, 0);
+      transform(x);
+      sbox7(key[ 28]^x[0], key[ 29]^x[1], key[ 30]^x[2], key[ 31]^x[3], x, 0);
+      transform(x);
+      sbox0(key[ 32]^x[0], key[ 33]^x[1], key[ 34]^x[2], key[ 35]^x[3], x, 0);
+      transform(x);
+      sbox1(key[ 36]^x[0], key[ 37]^x[1], key[ 38]^x[2], key[ 39]^x[3], x, 0);
+      transform(x);
+      sbox2(key[ 40]^x[0], key[ 41]^x[1], key[ 42]^x[2], key[ 43]^x[3], x, 0);
+      transform(x);
+      sbox3(key[ 44]^x[0], key[ 45]^x[1], key[ 46]^x[2], key[ 47]^x[3], x, 0);
+      transform(x);
+      sbox4(key[ 48]^x[0], key[ 49]^x[1], key[ 50]^x[2], key[ 51]^x[3], x, 0);
+      transform(x);
+      sbox5(key[ 52]^x[0], key[ 53]^x[1], key[ 54]^x[2], key[ 55]^x[3], x, 0);
+      transform(x);
+      sbox6(key[ 56]^x[0], key[ 57]^x[1], key[ 58]^x[2], key[ 59]^x[3], x, 0);
+      transform(x);
+      sbox7(key[ 60]^x[0], key[ 61]^x[1], key[ 62]^x[2], key[ 63]^x[3], x, 0);
+      transform(x);
+      sbox0(key[ 64]^x[0], key[ 65]^x[1], key[ 66]^x[2], key[ 67]^x[3], x, 0);
+      transform(x);
+      sbox1(key[ 68]^x[0], key[ 69]^x[1], key[ 70]^x[2], key[ 71]^x[3], x, 0);
+      transform(x);
+      sbox2(key[ 72]^x[0], key[ 73]^x[1], key[ 74]^x[2], key[ 75]^x[3], x, 0);
+      transform(x);
+      sbox3(key[ 76]^x[0], key[ 77]^x[1], key[ 78]^x[2], key[ 79]^x[3], x, 0);
+      transform(x);
+      sbox4(key[ 80]^x[0], key[ 81]^x[1], key[ 82]^x[2], key[ 83]^x[3], x, 0);
+      transform(x);
+      sbox5(key[ 84]^x[0], key[ 85]^x[1], key[ 86]^x[2], key[ 87]^x[3], x, 0);
+      transform(x);
+      sbox6(key[ 88]^x[0], key[ 89]^x[1], key[ 90]^x[2], key[ 91]^x[3], x, 0);
+      transform(x);
+      sbox7(key[ 92]^x[0], key[ 93]^x[1], key[ 94]^x[2], key[ 95]^x[3], x, 0);
+      transform(x);
+      sbox0(key[ 96]^x[0], key[ 97]^x[1], key[ 98]^x[2], key[ 99]^x[3], x, 0);
+      transform(x);
+      sbox1(key[100]^x[0], key[101]^x[1], key[102]^x[2], key[103]^x[3], x, 0);
+      transform(x);
+      sbox2(key[104]^x[0], key[105]^x[1], key[106]^x[2], key[107]^x[3], x, 0);
+      transform(x);
+      sbox3(key[108]^x[0], key[109]^x[1], key[110]^x[2], key[111]^x[3], x, 0);
+      transform(x);
+      sbox4(key[112]^x[0], key[113]^x[1], key[114]^x[2], key[115]^x[3], x, 0);
+      transform(x);
+      sbox5(key[116]^x[0], key[117]^x[1], key[118]^x[2], key[119]^x[3], x, 0);
+      transform(x);
+      sbox6(key[120]^x[0], key[121]^x[1], key[122]^x[2], key[123]^x[3], x, 0);
+      transform(x);
+      sbox7(key[124]^x[0], key[125]^x[1], key[126]^x[2], key[127]^x[3], x, 0);
+
+      x[0] ^= key[128];
+      x[1] ^= key[129];
+      x[2] ^= key[130];
+      x[3] ^= key[131];
+
+      for (int j = x.length-1; j >= 0; j--) {
+         out[o++] = (byte) (x[j] >>> 24);
+         out[o++] = (byte) (x[j] >>> 16);
+         out[o++] = (byte) (x[j] >>>  8);
+         out[o++] = (byte)  x[j];
+      }
+   }
+
+   public
+   void decrypt(byte[] in, int i, byte[] out, int o, Object K, int bs) {
+      int[] key = (int[]) K;
+      int[] x = new int[4];
+      x[3] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+      x[2] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+      x[1] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+      x[0] = (in[i++] & 0xff) << 24 | (in[i++] & 0xff) << 16 |
+             (in[i++] & 0xff) <<  8 | (in[i++] & 0xff);
+
+      sboxI7(key[128]^x[0], key[129]^x[1], key[130]^x[2], key[131]^x[3], x, 0);
+      transformInv(x, key, 124);
+      sboxI6(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key, 120);
+      sboxI5(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key, 116);
+      sboxI4(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key, 112);
+      sboxI3(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key, 108);
+      sboxI2(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key, 104);
+      sboxI1(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key, 100);
+      sboxI0(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  96);
+      sboxI7(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  92);
+      sboxI6(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  88);
+      sboxI5(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  84);
+      sboxI4(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  80);
+      sboxI3(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  76);
+      sboxI2(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  72);
+      sboxI1(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  68);
+      sboxI0(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  64);
+      sboxI7(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  60);
+      sboxI6(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  56);
+      sboxI5(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  52);
+      sboxI4(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  48);
+      sboxI3(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  44);
+      sboxI2(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  40);
+      sboxI1(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  36);
+      sboxI0(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  32);
+      sboxI7(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  28);
+      sboxI6(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  24);
+      sboxI5(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  20);
+      sboxI4(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  16);
+      sboxI3(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,  12);
+      sboxI2(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,   8);
+      sboxI1(x[0], x[1], x[2], x[3], x, 0);
+      transformInv(x, key,   4);
+      sboxI0(x[0], x[1], x[2], x[3], x, 0);
+
+      x[0] ^= key[0];
+      x[1] ^= key[1];
+      x[2] ^= key[2];
+      x[3] ^= key[3];
+
+      for (int j = x.length-1; j >= 0; j--) {
+         out[o++] = (byte) (x[j] >>> 24);
+         out[o++] = (byte) (x[j] >>> 16);
+         out[o++] = (byte) (x[j] >>>  8);
+         out[o++] = (byte)  x[j];
+      }
+   }
+
+ // Own methods
+   // -----------------------------------------------------------------
+
+   /** Serpent's linear transformation. */
+   private void transform(int[] x) {
+      x[0] = x[0] << 13 | x[0] >>> 19;
+      x[2] = x[2] << 3 | x[2] >>> 29;
+      x[1] = x[1] ^ x[0] ^ x[2];
+      x[3] = x[3] ^ x[2] ^ (x[0] << 3);
+      x[1] = x[1] << 1 | x[1] >>> 31;
+      x[3] = x[3] << 7 | x[3] >>> 25;
+      x[0] = x[0] ^ x[1] ^ x[3];
+      x[2] = x[2] ^ x[3] ^ (x[1] << 7);
+      x[0] = x[0] << 5 | x[0] >>> 27;
+      x[2] = x[2] << 22 | x[2] >>> 10;
+   }
+
+   /**
+    * The inverse linear transformation. The XOR with the key is done
+    * here to save space above.
+    *
+    * @param x The current block being decrypted.
+    * @param key The session key.
+    * @param off The index in the key to start from.
+    */
+   private void transformInv(int[] x, int[] key, int off) {
+      x[0] ^= key[off++];
+      x[1] ^= key[off++];
+      x[2] ^= key[off++];
+      x[3] ^= key[off++];
+
+      x[2] = x[2] >>> 22 | x[2] << 10;
+      x[0] = x[0] >>> 5 | x[0] << 27;
+      x[2] = x[2] ^ x[3] ^ (x[1] << 7);
+      x[0] = x[0] ^ x[1] ^ x[3];
+      x[3] = x[3] >>> 7 | x[3] << 25;
+      x[1] = x[1] >>> 1 | x[1] << 31;
+      x[3] = x[3] ^ x[2] ^ (x[0] << 3);
+      x[1] = x[1] ^ x[0] ^ x[2];
+      x[2] = x[2] >>> 3 | x[2] << 29;
+      x[0] = x[0] >>> 13 | x[0] << 19;
+   }
+
+   // Bit-flip madness methods
+   //
+   // The following S-Box functions were developed by Dag Arne Osvik,
+   // and are described in his paper, "Speeding up Serpent". They are
+   // optimized to perform on the Pentium chips, but work well here too.
+   //
+   // The methods below are Copyright (C) 2000 Dag Arne Osvik.
+
+   // These methods may be de-assembler-ized (more than one operation in
+   // each statement) for readability (?) and speed (??).
+
+   /** S-Box 0. */
+   private void sbox0(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r1 ^ r2;
+      r3 ^= r0;
+      r1 = r1 & r3 ^ r0;
+      r0 = (r0 | r3) ^ r4;
+      r4 ^= r3;
+      r3 ^= r2;
+      r2 = (r2 | r1) ^ r4;
+      r4 = ~r4 | r1;
+      r1 ^= r3 ^ r4;
+      r3 |= r0;
+      w[off  ] = r1 ^ r3;
+      w[off+1] = r4 ^ r3;
+      w[off+2] = r2;
+      w[off+3] = r0;
+   }
+
+   /** The inverse of S-Box 0. */
+   private void sboxI0(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r1;
+      r2 = ~r2;
+      r1 = (r1 | r0) ^ r2;
+      r4 = ~r4;
+      r2 |= r4;
+      r1 ^= r3;
+      r0 ^= r4;
+      r2 ^= r0;
+      r0 &= r3;
+      r4 ^= r0;
+      r0 = (r0 | r1) ^ r2;
+      r3 = r3 ^ r4 ^ r0 ^ r1;
+      r2 = (r2 ^ r1) & r3;
+      w[off  ] = r0;
+      w[off+1] = r4 ^ r2;
+      w[off+2] = r1;
+      w[off+3] = r3;
+   }
+
+   /** S-Box 1. */
+   private void sbox1(int r0, int r1, int r2, int r3, int[] w, int off) {
+      r0 = ~r0;
+      int r4 = r0;
+      r2 = ~r2;
+      r0 &= r1;
+      r2 ^= r0;
+      r0 |= r3;
+      r3 ^= r2;
+      r1 ^= r0;
+      r0 ^= r4;
+      r4 |= r1;
+      r1 ^= r3;
+      r2 = (r2 | r0) & r4;
+      r0 ^= r1;
+      w[off  ] = r2;
+      w[off+1] = r0 & r2 ^ r4;
+      w[off+2] = r3;
+      w[off+3] = r1 & r2 ^ r0;
+   }
+
+   /** The inverse of S-Box 1. */
+   private void sboxI1(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r1;
+      r1 ^= r3;
+      r3 = r3 & r1 ^ r0;
+      r4 ^= r2;
+      r2 ^= r3;
+      r0 = (r0 | r1) ^ r4 | r2;
+      r1 ^= r3;
+      r0 ^= r1;
+      r1 = (r1 | r3) ^ r0;
+      r4 = ~r4 ^ r1;
+      w[off  ] = r4;
+      w[off+1] = r0;
+      w[off+2] = r3 ^ ((r1 | r0) ^ r0 | r4);
+      w[off+3] = r2;
+   }
+
+   /** S-Box 2. */
+   private void sbox2(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r0;
+      r0 = r0 & r2 ^ r3;
+      r2 = r2 ^ r1 ^ r0;
+      r3 = (r3 | r4) ^ r1;
+      r4 ^= r2;
+      r1 = r3;
+      r3 = (r3 | r4) ^ r0;
+      r0 &= r1;
+      r4 ^= r0;
+      w[off  ] = r2;
+      w[off+1] = r3;
+      w[off+2] = r1 ^ r3 ^ r4;
+      w[off+3] = ~r4;
+   }
+
+   /** The inverse of S-Box 2. */
+   private void sboxI2(int r0, int r1, int r2, int r3, int[] w, int off) {
+      r2 ^= r3;
+      r3 ^= r0;
+      int r4 = r3;
+      r3 = r3 & r2 ^ r1;
+      r1 = (r1 | r2) ^ r4;
+      r4 &= r3;
+      r2 ^= r3;
+      r4 = r4 & r0 ^ r2;
+      r3 = ~r3;
+      r2 = (r2 & r1 | r0) ^ r3;
+      r0 = (r0 ^ r3) & r1;
+      w[off  ] = r1;
+      w[off+1] = r4;
+      w[off+2] = r2;
+      w[off+3] = r3 ^ r4 ^ r0;
+   }
+
+   /** S-Box 3. */
+   private void sbox3(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r0;
+      r0 |= r3;
+      r3 ^= r1;
+      r1 &= r4;
+      r4 = r4 ^ r2 | r1;
+      r2 ^= r3;
+      r3 = r3 & r0 ^ r4;
+      r0 ^= r1;
+      r4 = r4 & r0 ^ r2;
+      r1 = (r1 ^ r3 | r0) ^ r2;
+      r0 ^= r3;
+      w[off  ] = (r1 | r3) ^ r0;
+      w[off+1] = r1;
+      w[off+2] = r3;
+      w[off+3] = r4;
+   }
+
+   /** Inverse of S-Box 3. */
+   private void sboxI3(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r2;
+      r2 ^= r1;
+      r0 ^= r2;
+      r4 = r4 & r2 ^ r0;
+      r0 &= r1;
+      r1 ^= r3;
+      r3 |= r4;
+      r2 ^= r3;
+      r0 ^= r3;
+      r1 ^= r4;
+      r3 = r3 & r2 ^ r1;
+      r1 = (r1 ^ r0 | r2) ^ r4;
+      w[off  ] = r2;
+      w[off+1] = r1;
+      w[off+2] = r3;
+      w[off+3] = r0 ^ r3 ^ r1;
+   }
+
+   /** S-Box 4. */
+   private void sbox4(int r0, int r1, int r2, int r3, int[] w, int off) {
+      r1 ^= r3;
+      int r4 = r1;
+      r3 = ~r3;
+      r2 ^= r3;
+      r3 ^= r0;
+      r1 = r1 & r3 ^ r2;
+      r4 ^= r3;
+      r0 ^= r4;
+      r2 = r2 & r4 ^ r0;
+      r0 &= r1;
+      r3 ^= r0;
+      r4 = (r4 | r1) ^ r0;
+      w[off  ] = r1;
+      w[off+1] = r4 ^ (r2 & r3);
+      w[off+2] = ~((r0 | r3) ^ r2);
+      w[off+3] = r3;
+   }
+
+   /** Inverse of S-Box 4. */
+   private void sboxI4(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r2;
+      r2 = r2 & r3 ^ r1;
+      r1 = (r1 | r3) & r0;
+      r4 = r4 ^ r2 ^ r1;
+      r1 &= r2;
+      r0 = ~r0;
+      r3 ^= r4;
+      r1 ^= r3;
+      r3 = r3 & r0 ^ r2;
+      r0 ^= r1;
+      r3 ^= r0;
+      w[off  ] = r0;
+      w[off+1] = r3 ^ r0;
+      w[off+2] = (r2 & r0 ^ r4 | r3) ^ r1;
+      w[off+3] = r4;
+   }
+
+   /** S-Box 5. */
+   private void sbox5(int r0, int r1, int r2, int r3, int[] w, int off) {
+      r0 ^= r1;
+      r1 ^= r3;
+      int r4 = r1;
+      r3 = ~r3;
+      r1 &= r0;
+      r2 ^= r3;
+      r1 ^= r2;
+      r2 |= r4;
+      r4 ^= r3;
+      r3 = r3 & r1 ^ r0;
+      r4 = r4 ^ r1 ^ r2;
+      w[off  ] = r1;
+      w[off+1] = r3;
+      w[off+2] = r0 & r3 ^ r4;
+      w[off+3] = ~(r2 ^ r0) ^ (r4 | r3);
+   }
+
+   /** Inverse of S-Box 5. */
+   private void sboxI5(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r3;
+      r1 = ~r1;
+      r2 ^= r1;
+      r3 = (r3 | r0) ^ r2;
+      r4 ^= r3;
+      r2 = (r2 | r1) & r0 ^ r4;
+      r4 = (r4 | r0) ^ r1 ^ r2;
+      r1 = r1 & r2 ^ r3;
+      r3 &= r4;
+      r4 ^= r1;
+      w[off  ] = r1;
+      w[off+1] = ~r4;
+      w[off+2] = r3 ^ r4 ^ r0;
+      w[off+3] = r2;
+   }
+
+   /** S-Box 6. */
+   private void sbox6(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r3;
+      r2 = ~r2;
+      r3 = r3 & r0 ^ r2;
+      r0 ^= r4;
+      r2 = (r2 | r4) ^ r0;
+      r1 ^= r3;
+      r0 |= r1;
+      r2 ^= r1;
+      r4 ^= r0;
+      r0 = (r0 | r3) ^ r2;
+      r4 = r4 ^ r3 ^ r0;
+      w[off  ] = r0;
+      w[off+1] = r1;
+      w[off+2] = r4;
+      w[off+3] = r2 & r4 ^ ~r3;
+   }
+
+   /** Inverse of S-Box 6. */
+   private void sboxI6(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r2;
+      r0 ^= r2;
+      r2 &= r0;
+      r4 ^= r3;
+      r3 ^= r1;
+      r2 = ~r2 ^ r3;
+      r4 |= r0;
+      r0 ^= r2;
+      r3 ^= r4;
+      r4 ^= r1;
+      r1 = r1 & r3 ^ r0;
+      r0 = r0 ^ r3 | r2;
+      w[off  ] = r1;
+      w[off+1] = r2;
+      w[off+2] = r4 ^ r0;
+      w[off+3] = r3 ^ r1;
+   }
+
+   /** S-Box 7. */
+   private void sbox7(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r1;
+      r1 = (r1 | r2) ^ r3;
+      r4 ^= r2;
+      r2 ^= r1;
+      r3 = (r3 | r4) & r0;
+      r4 ^= r2;
+      r3 ^= r1;
+      r1 = (r1 | r4) ^ r0;
+      r0 = (r0 | r4) ^ r2;
+      r1 ^= r4;
+      r2 ^= r1;
+      w[off  ] = r4 ^ (~r2 | r0);
+      w[off+1] = r3;
+      w[off+2] = r1 & r0 ^ r4;
+      w[off+3] = r0;
+   }
+
+   /** Inverse of S-Box 7. */
+   private void sboxI7(int r0, int r1, int r2, int r3, int[] w, int off) {
+      int r4 = r2;
+      r2 = ~(r2 ^ r0);
+      r0 &= r3;
+      r4 |= r3;
+      r3 ^= r1;
+      r1 |= r0;
+      r0 ^= r2;
+      r2 &= r4;
+      r3 &= r4;
+      r1 ^= r2;
+      r2 ^= r0;
+      r0 = (r0 | r2) ^ r3;
+      r4 ^= r1;
+      w[off  ] = r3 ^ r4 ^ r2;
+      w[off+1] = r0;
+      w[off+2] = r1;
+      w[off+3] = (r4 | r0) ^ r2;
+   }
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]