www.pudn.com > SmartCardSrc.zip > sdes.cpp


//------------------------------------------------------------------------------ 
// 
// Copyright (c) 1999-2005  Matt Brunk   
// 
// This program is free software; you can redistribute it and/or modify 
// it under the terms of the GNU General Public License VERSION 2 as 
// published by the Free Software Foundation.  You are not allowed to 
// use any other version of the license; unless you got the explicit 
// permission from the author to do so. 
// 
// 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; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
// 
//------------------------------------------------------------------------------ 
#include  
#include "sdes.h" 
 
//U8	SDES::s_key = 0x097; 
U16	SDES::s_key = 0x06D; 
 
// create the s-boxes 
static const U8 S0[4][4] = 
{ 
    { 1, 0, 3, 2 }, 
    { 3, 2, 1, 0 }, 
    { 0, 2, 1, 3 }, 
    { 3, 1, 0, 3 } 
}; 
static const U8 S1[4][4] = 
{ 
    { 0, 1, 2, 3 }, 
    { 2, 0, 1, 3 }, 
    { 3, 0, 1, 0 }, 
    { 2, 1, 0, 3 } 
}; 
 
/* 
   I am using macros for two reasons : 
   1. they avoid the overhead of a function call 
   2. they are more fun that a barrel of IS students 
   If you want to see how macros expand use : gcc -E 
 */ 
 
// bit x of y, evaluate to 1 or 0 ( true/false ) 
#define B(x,y) ( ((y) >> (x)) & 0x01) 
 
/* 
   bit reordering permutations and expansions 
   the bit remapping is prior to each 
   these are all defined as macros 
 */ 
 
// p10  9876543210 -> 7583609124 
#define p10(x) ( B(7,x) << 9 | B(5,x) << 8 | B(8,x) << 7 | B(3,x) << 6 | \ 
        B(6,x) << 5 | B(0,x) << 4 | B(9,x) << 3 | B(1,x) << 2 | \ 
        B(2,x) << 1 | B(4,x) ) 
 
    //p8   9876543210 -> 47362501 
#define p8(x) ( B(4,x) << 7 | B(7,x) << 6 | B(3,x) << 5 | B(6,x) << 4 | \ 
        B(2,x) << 3 | B(5,x) << 2 | B(0,x) << 1 | B(1,x) ) 
 
    //p4   3210 -> 2013 
#define p4(x) ( B(2,x) << 3 | B(0,x) << 2 | B(1,x) << 1 | B(3,x) ) 
 
    //ip   76543210 -> 62574031 
#define ip(x) ( B(6,x) << 7 | B(2,x) << 6 | B(5,x) << 5 | B(7,x) << 4 | \ 
        B(4,x) << 3 | B(0,x) << 2 | B(3,x) << 1 | B(1,x) ) 
 
    //ip_inv 76543210 -> 47531602 
#define ip_inv(x) ( B(4,x) << 7 | B(7,x) << 6 | B(5,x) << 5 | B(3,x) << 4 | \ 
        B(1,x) << 3 | B(6,x) << 2 | B(0,x) << 1 | B(2,x) ) 
 
    //ep   3210 -> 03212103 
#define ep(x) ( B(0,x) << 7 | B(3,x) << 6 | B(2,x) << 5 | B(1,x) << 4 | \ 
        B(2,x) << 3 | B(1,x) << 2 | B(0,x) << 1 | B(3,x) ) 
 
    //sw   76543210 -> 32107654 
#define sw(x) ( B(3,x) << 7 | B(2,x) << 6 | B(1,x) << 5 | B(0,x) << 4 | \ 
        B(7,x) << 3 | B(6,x) << 2 | B(5,x) << 1 | B(4,x) ) 
 
    // actually used these 
    // rotate x left y bits, total size is 5 bits 
#define ROT_L5(x,y) ((( (x) << (y) ) | ( (x) >> (5-y) )) & 0x1F ) 
    // get the right 5 bits of x 
#define RIGHT5(x) ( (x) & 0x1F ) 
    // get the left 5 bits of x 
#define LEFT5(x) ( ( (x) >> 5 ) & 0x1F ) 
    // get the right 4 bits of x 
#define RIGHT4(x) ( (x) & 0x0F ) 
    // get the left 4 bits of x 
#define LEFT4(x) ( ( (x) >> 4 ) & 0x0F ) 
 
    // print x as a 10 bit value 
void p_bits( U8 x ) 
{ 
    char arr[13] = "00 0000 0000"; 
    int i, j; 
    for( i = 9, j = 0 ; i >= 0 ; --i, ++j ) 
    { 
        // leave 2 and 7 as spaces for readability 
        if ( ( j == 2 ) || ( j == 7 ) ) 
        { 
            ++j; 
        } 
        if( B(i,x ) ) 
        { 
            arr[ j ] = '1'; 
        } 
    } 
    printf ( "%s\n", arr ); 
} 
 
#ifdef DEBUG 
// clean up the debugging stuff 
void debugf( char * s, U8 x ) 
{ 
    printf( "%s", s ); 
    p_bits( x ); 
} 
#else 
// make it an empty statement 
#define debugf(s,x) ; 
#endif 
 
// real des functions 
void subkeys( U16 k, U8 * k1, U8 * k2 ) 
{ 
    U16 n = p10( k ); 
    // split it into two 5 bit halves 
    U8 l = LEFT5( n ); 
    U8 r = RIGHT5( n ); 
    U16 tmp; 
    debugf( "ep(k) = ", n ); 
    // rotate each half left by one 
    l = ROT_L5( l, 1 ); 
    r = ROT_L5( r, 1 ); 
    tmp = ( l << 5 ) | r;   // join them 
    debugf( "ls-1 =  ", tmp ); 
    *k1 = p8( tmp ); 
    debugf( "k1 =    ", *k1 ); 
    // rotate each half left by two 
    l = ROT_L5( l, 2 ); 
    r = ROT_L5( r, 2 ); 
    tmp = ( l << 5 ) | r;   // join them 
    debugf( "ls-2 =  ", tmp ); 
    *k2 = p8( tmp ); 
    debugf( "k2 =    ", *k2 ); 
} 
 
U8 F( U8 x, U8 k ) 
{ 
    U8 row,col; 
    U16 rval; 
    U8 a = ep(x) ^ k; // expand and add key 
    U8 l = LEFT4( a ); 
    U8 r = RIGHT4( a ); 
    // row bits 30 , col bits 21 
    // lookup left 4 in S0 
    row = ( B(3, l ) << 1 ) | B(0, l ); 
    col = ( B(2, l ) << 1 ) | B(1, l ); 
    rval = S0[row][col] << 2;   // the left 2 bits 
    // lookup right 4 in S1 
    row = ( B(3, r ) << 1 ) | B(0, r ); 
    col = ( B(2, r ) << 1 ) | B(1, r ); 
    rval |= S1[row][col];       // the right 2 bits 
    rval = p4(rval); 
    return (U8)rval; 
} 
 
// fk(L,R,SK) = ( L ^ F(R,SK),R ) 
U8 f_k( U8 x, U8 k ) 
{ 
    U8 l = LEFT4( x ); 
    U8 r = RIGHT4( x ); 
    U8 y = l ^ F( r, k );			// "add" them, really xor 
    U8 rval = (U8)(( y << 4 ) | r); // join them 
    return rval; 
} 
 
U8 SDES::Encrypt(U8 in) 
{ 
    U8 k1,k2;     // key and subkeys 
    subkeys( s_key, &k1, &k2 ); 
 
    U8 x = ip( in ); 
    x = f_k( x , k1 ); 
    x = sw( x ); 
    x = f_k( x , k2 ); 
    x = ip_inv( x ); 
    return x; 
} 
 
U8 SDES::Decrypt(U8 in) 
{ 
    U8 k1,k2;     // key and subkeys 
    subkeys( s_key, &k1, &k2 ); 
 
    U8 x = ip( in ); 
    x = f_k( x , k2 ); 
    x = sw( x ); 
    x = f_k( x , k1 ); 
    x = ip_inv( x ); 
    return x; 
}