Cryptography Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 4.00

DES Algorithm - Illustrated with Java Programs

Part:   1  2  3  4  5  6 

(Continued from previous part...)

   private static byte[] substitution6x4(byte[] in) {
      in = splitBytes(in,6); // Splitting byte[] into 6-bit blocks
//    printBytes(in,"R: After splitting");
      byte[] out = new byte[in.length/2];
      int lhByte = 0;
      for (int b=0; b<in.length; b++) { // Should be sub-blocks
         byte valByte = in[b];
         int r = 2*(valByte>>7&0x0001)+(valByte>>2&0x0001); // 1 and 6
         int c = valByte>>3&0x000F; // Middle 4 bits
         int hByte = S[64*b+16*r+c]; // 4 bits (half byte) output
         if (b%2==0) lhByte = hByte; // Left half byte
         else out[b/2] = (byte) (16*lhByte + hByte);
      }
      return out;
   }
   private static byte[] splitBytes(byte[] in, int len) {
      int numOfBytes = (8*in.length-1)/len + 1;
      byte[] out = new byte[numOfBytes];
      for (int i=0; i<numOfBytes; i++) {
         for (int j=0; j<len; j++) {
            int val = getBit(in, len*i+j); 
            setBit(out,8*i+j,val);
         }
      }
      return out;
   }
   private static byte[] concatenateBits(byte[] a, int aLen, byte[] b, 
      int bLen) {
      int numOfBytes = (aLen+bLen-1)/8 + 1;
      byte[] out = new byte[numOfBytes];
      int j = 0;
      for (int i=0; i<aLen; i++) {
         int val = getBit(a,i);
         setBit(out,j,val);
         j++;
      }
      for (int i=0; i<bLen; i++) {
         int val = getBit(b,i);
         setBit(out,j,val);
         j++;
      }
      return out;
   }
   private static byte[] selectBits(byte[] in, int pos, int len) {
      int numOfBytes = (len-1)/8 + 1;
      byte[] out = new byte[numOfBytes];
      for (int i=0; i<len; i++) {
         int val = getBit(in,pos+i);
         setBit(out,i,val);
      }
      return out;
   }
   private static byte[] selectBits(byte[] in, int[] map) {
      int numOfBytes = (map.length-1)/8 + 1;
      byte[] out = new byte[numOfBytes];
      for (int i=0; i<map.length; i++) {
         int val = getBit(in,map[i]-1);
         setBit(out,i,val);
//       System.out.println("i="+i+", pos="+(map[i]-1)+", val="+val);
      }
      return out;
   }
   private static int getBit(byte[] data, int pos) {
      int posByte = pos/8; 
      int posBit = pos%8;
      byte valByte = data[posByte];
      int valInt = valByte>>(8-(posBit+1)) & 0x0001;
      return valInt;
   }
   private static void setBit(byte[] data, int pos, int val) {
      int posByte = pos/8; 
      int posBit = pos%8;
      byte oldByte = data[posByte];
      oldByte = (byte) (((0xFF7F>>posBit) & oldByte) & 0x00FF);
      byte newByte = (byte) ((val<<(8-(posBit+1))) | oldByte);
      data[posByte] = newByte;
   }
   private static void printBytes(byte[] data, String name) {
      System.out.println("");
      System.out.println(name+":");
      for (int i=0; i<data.length; i++) {
         System.out.print(byteToBits(data[i])+" ");
      }
      System.out.println();
   }
   private static String byteToBits(byte b) {
      StringBuffer buf = new StringBuffer();
      for (int i=0; i<8; i++)
         buf.append((int)(b>>(8-(i+1)) & 0x0001));
      return buf.toString();
   }
   private static byte[][] getTestSubkeys() {
      String[] strKeys = {
         " 00011011 00000010 11101111 11111100 01110000 01110010",//1
         " 01111001 10101110 11011001 11011011 11001001 11100101",//2
         " 01010101 11111100 10001010 01000010 11001111 10011001",//3
         " 01110010 10101101 11010110 11011011 00110101 00011101",//4
         " 01111100 11101100 00000111 11101011 01010011 10101000",//5
         " 01100011 10100101 00111110 01010000 01111011 00101111",//6
         " 11101100 10000100 10110111 11110110 00011000 10111100",//7
         " 11110111 10001010 00111010 11000001 00111011 11111011",//8
         " 11100000 11011011 11101011 11101101 11100111 10000001",//9
         " 10110001 11110011 01000111 10111010 01000110 01001111",//0
         " 00100001 01011111 11010011 11011110 11010011 10000110",//1
         " 01110101 01110001 11110101 10010100 01100111 11101001",//2
         " 10010111 11000101 11010001 11111010 10111010 01000001",//3
         " 01011111 01000011 10110111 11110010 11100111 00111010",//4
         " 10111111 10010001 10001101 00111101 00111111 00001010",//5
         " 11001011 00111101 10001011 00001110 00010111 11110101"};
      byte[][] subKeys = new byte[16][];
      for (int k=0; k<16; k++) {
         byte[] theKey = new byte[6];
         for (int i=0; i<6; i++) {
            String strByte = strKeys[k].substring(9*i+1,9*i+1+8);
            theKey[i] = (byte) Integer.parseInt(strByte,2);
         }
         subKeys[k] = theKey;
      }
      return subKeys;
   }
   private static byte[] getTestMsg() {
      String strMsg = " 00000001 00100011 01000101 01100111"
                     +" 10001001 10101011 11001101 11101111";
      byte[] theMsg = new byte[8];
      for (int i=0; i<8; i++) {
         String strByte = strMsg.substring(9*i+1,9*i+1+8);
         theMsg[i] = (byte) Integer.parseInt(strByte,2);
      }
      return theMsg;
   }
   private static boolean validateCipher(byte[] cipher ) {
      String strCipher = " 10000101 11101000 00010011 01010100"
                        +" 00001111 00001010 10110100 00000101";
      boolean ok = true;
      for (int i=0; i<8; i++) {
         String strByte = strCipher.substring(9*i+1,9*i+1+8);
         byte cipherByte = (byte) Integer.parseInt(strByte,2);
         if (cipherByte!=cipher[i]) ok = false;
      }
      return ok;
   }
}

(Continued on next part...)

Part:   1  2  3  4  5  6 

Dr. Herong Yang, updated in 2007
Cryptography Tutorials - Herong's Tutorial Notes - DES Algorithm - Illustrated with Java Programs