/*
   Copyright 2000(c) Burton Rosenberg. All rights reserved.
   Mon Sep 18 12:18:49 EDT 2000
*/

class SBox
{
    int [][] sbox = null ;
    int [] sbox_ = null ;
    int sboxNumber = 0 ;

    final static int [] SBOX1 = 
         { 14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
            0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
            4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
           15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13 } ;

    final static int [] SBOX2 = 
         { 15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
            3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
            0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
           13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9 } ;

    final static int [] SBOX3 = 
         { 10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
           13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
           13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
            1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12 } ;

    final static int [] SBOX4 = 
         {  7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
           13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
           10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
            3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14 } ;

    final static int [] SBOX5 = 
         {  2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
           14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
            4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
           11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3 } ;

    final static int [] SBOX6 = 
         { 12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
           10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
            9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
            4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13 } ;

    final static int [] SBOX7 = 
         {  4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
           13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
            1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
            6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12 } ;

    final static int [] SBOX8 = 
         { 13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
            1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
            7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
            2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11 } ;

    SBox(int sboxNumber)
    {
        switch(sboxNumber)
        {
        case 0:
            sbox_ = SBOX1 ;
            break ;

        case 1:
            sbox_ = SBOX2 ;
            break ;

        case 2:
            sbox_ = SBOX3 ;
            break ;

        case 3:
            sbox_ = SBOX4 ;
            break ;

        case 4:
            sbox_ = SBOX5 ;
            break ;

        case 5:
            sbox_ = SBOX6 ;
            break ;

        case 6:
            sbox_ = SBOX7 ;
            break ;

        case 7:
            sbox_ = SBOX8 ;
            break ;

        default:
            sbox_ = null ;
        }
        sbox = new int [64][4] ;
        for ( int i=0; i<64; i++ )
        {
            int sboxValue = sbox_[i] ;
            for ( int j=3; j>=0; j-- )
            {
               sbox[i][j] = sboxValue & 0x01 ;
               sboxValue >>= 1 ;
            }
        }
        this.sboxNumber = sboxNumber ;
    }

    int [] map( int [] sboxIn )
    {
       // sboxIn.length == 6 ;
       int i ;
       i = ( sboxIn[0] << 5 )
           | ( sboxIn[5] << 4 )
           | ( sboxIn[1] << 3 )
           | ( sboxIn[2] << 2 )
           | ( sboxIn[3] << 1 )
           | ( sboxIn[4] ) ;
       return  sbox[i] ;
    }

    int map( int sboxIn )
    {
       int iCol = (sboxIn & 0x1e)/2 ;
       int iRow = ((sboxIn>31) ? 2 : 0 ) + (sboxIn & 0x1) ;
       return sbox_[iRow*16+iCol] ;
    }

    static void printSBox( int sboxNumber )
    {
        SBox sbox = new SBox( sboxNumber ) ;
        for ( int row=0; row<4; row++ )
        {
            for ( int col=0; col<16; col++ )
            {
               int [] sin = DesEtc.unpackAux( (long) 2*col, 6 ) ;
               if ( (row & 1) != 0 ) sin[5] = 1 ;
               if ( (row & 2) != 0 ) sin[0] = 1 ;
               int [] sout = sbox.map(sin) ;
               int sout_ = (int) DesEtc.packAux( sout, 4 ) ;
               String s = Integer.toString( sout_ ) ;
               if ( s.length()==1 ) s = " " + s ;
               System.out.print( s + " " ) ;
            }
            System.out.println() ;
        }
    }
}

