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; }