
class FBox
{
    SBox [] sbox  ;
    EBox ebox = new EBox() ;
    PBox pbox = new PBox() ;

    int [] zeroKey = null ;
    int [] eboxOut = new int[48] ;
    int [] pboxIn = new int[32] ;
    int [] sboxOut = null ;
    int [] sboxIn = new int[6] ;

    int [] sboxInX = new int[48] ;

    int [] fboxOut = new int [32] ;

    FBox()
    {
        sbox = new SBox[8] ;
        for ( int i=0; i<8; i++ )
        {
           sbox[i] = new SBox(i) ;
        }
        zeroKey = new int[48] ;
        for ( int j=0; j<48; j++ )
        {
            zeroKey[j] = 0 ;
        }
    }

    void doFBox( int [] v )
    {
        doFBox( v, zeroKey ) ;
    }

    void doFBoxVerbose( int [] v )
    {
        doFBoxVerbose( v, zeroKey ) ;
    }

    void doFBoxAux( int [] v, int [] subkey )
    {
        int eboxIndex = 0 ;
        int pboxIndex = 0 ;
        
        ebox.permutation( eboxOut, v ) ;
        for ( int i=0; i<8; i++)
        {
            for ( int j=0; j<6; j++ )
            {
               sboxInX[eboxIndex] = 
               sboxIn[j] =  eboxOut[eboxIndex] ^ subkey[eboxIndex] ;
               eboxIndex++ ;
            }
            sboxOut = sbox[i].map(sboxIn) ;
            for ( int k=0; k<4; k++ )
            {
                pboxIn[pboxIndex] = sboxOut[k] ;
                pboxIndex++ ;
            }
        }
    }

    void doFBox( int [] v, int [] subkey )
    {
        doFBoxAux( v, subkey ) ;
        pbox.permutation(v, pboxIn) ;
    }

    void doFBox( int [] fboxOut, int [] fboxIn, int [] subkey )
    {
        doFBoxAux( fboxIn, subkey ) ;
        pbox.permutation( fboxOut, pboxIn ) ;
    }

    void doFBoxVerbose( int [] v, int [] subkey )
    {
        doFBoxAux( v, subkey ) ;
        System.out.println("======== Input ========" ) ;
        print32(v) ;
        System.out.println("---------- E ----------") ;
        print48(eboxOut) ;
        System.out.println("---------- K ----------") ;
        print48(subkey) ;
        System.out.println("---------- + ----------") ;
        print48(sboxInX) ;
        System.out.println("---------- S ----------") ;
        System.out.println("S1-S2-S3-S4-S5-S6-S7-S8") ;
        System.out.println("---------- S ----------") ;
        print32(pboxIn) ;
        System.out.println("---------- P ----------") ;
        pbox.permutation(v, pboxIn) ;
        print32(v) ;
        System.out.println("======== Output =======") ;

    }

    void desOneRoundSwapped( int [] leftInRightOut, int [] rightInLeftOut,
                             int [] subkey )
    {
          doFBox( fboxOut, rightInLeftOut, subkey ) ;
          for ( int i=0; i<32; i++ ) 
          {
              leftInRightOut[i] ^= fboxOut[i] ;
          }
    }

    static void print48( int [] v )
    {
        int k = 0 ;
        int l ;
        for ( int i=0; i<8; i++ )
        {
            l = 0 ;
            for ( int j=0; j<6; j++ )
            {
                l <<= 1 ;
                l |= v[k++] ;
            }
            String s = Integer.toString( l, 16 ) ;
            if ( s.length()==1 ) s = "0" + s ;
            System.out.print( s + " " ) ;
        }
        System.out.println() ;
    }

    static void print32( int [] v )
    {
        int k = 0 ;
        int l ;
        for ( int i=0; i<8; i++ )
        {
            l = 0 ;
            for ( int j=0; j<4; j++ )
            {
                l <<= 1 ;
                l |= v[k++] ;
            }
            System.out.print( " " + Integer.toString( l, 16 ) + " " ) ;
        }
        System.out.println() ;
    }
}

