[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

No Subject



/* SAFER SK-128 designed by James L. Massey who did not do this
   conversion and is not responsible for any bugs in it.

   This a 'C' conversion of the reference Turbo Pascal implementation

Examples of Encryption with SAFER SK-128 (i.e., 
with the strengthened key schedule of 128 bits.)

PLAINTEXT is        1   2   3   4   5   6   7   8
KEY Ka is           0   0   0   0   0   0   0   1
KEY Kb is           0   0   0   0   0   0   0   1
after round 1     131 177  53  27 130 249 141 121
after round 2      68  73  32 102 134  54 206  57
after round 3     248 213 217  11  23  68   0 243
after round 4     194  62 109  79  24  18  13  84
after round 5     153 156 246 172  40  72 173  39
after round 6     154 242  34   6  61  35 216  28
after round 7     100  31 172  67  44  75 133 219
after round 8      78 226 239 135 210  83  93  72
after round 9      72  64  46 195 163 159 243 114
after round10       3 133  76 190 191  52 220 123
CRYPTOGRAM is      65  76  84  90 182 153  74 247
 
PLAINTEXT is        1   2   3   4   5   6   7   8
KEY Ka is           1   2   3   4   5   6   7   8
KEY Kb is           0   0   0   0   0   0   0   0
after round 1      64 214  74 216 103 222  26  54
after round 2      61  14  68  15  46 111 124  80
after round 3     197 124  96  59 255  24   2  30
after round 4      63  59 214 103 236 166 153  24
after round 5      66 254  26  45 152 223   5 122
after round 6      89  47  58 105 161  38 135  45
after round 7      19 202 174  44  57 206  52  25
after round 8      78 179 113 208 169  26 121  22
after round 9      53  17  81 215 120  37 206 246
after round10     189 177   9   0 186  82 208 253
CRYPTOGRAM is     255 120  17 228 179 167  46 113
 
PLAINTEXT is        1   2   3   4   5   6   7   8
KEY Ka is           0   0   0   0   0   0   0   0
KEY Kb is           1   2   3   4   5   6   7   8
after round 1      95 186 209 220 166  66 213  10
after round 2     200  65 189 120  96 135  42 166
after round 3      64 169  43 166 132 171  31  40
after round 4     199 167  76 189 145 158 241  19
after round 5      71  55 184 212 108 198  77 108
after round 6     173 197 139  11  17  48  97  59
after round 7      17  51 142   4 170   7 207 124
after round 8      62 205 253 225 167 179 228 202
after round 9     133 168 127 138 193 243  34 226
after round10      59 194  69 220 220 231 123 148
CRYPTOGRAM is      73 201 157 152 165 188  89   8
*/


#include <stdio.h>


/* globals */

unsigned char a1,a2,a3,a4,a5,a6,a7,a8,
              b1,b2,b3,b4,b5,b6,b7,b8,
              r;

unsigned char k[25][8],ka[9],kb[9];

int logtab[256],exptab[256],i,j,n;

mat1(p1,p2,q1,q2)
unsigned char p1,p2,*q1,*q2;
{
  *q2=p1+p2;
  *q1=*q2+p1;
}

invmat1(p1,p2,q1,q2)
unsigned char p1,p2,*q1,*q2;
{
  *q1=p1-p2;
  *q2=-*q1+p2;
}

init_tables()
{
/* This portion of the program computes the powers of the primitive
   element 45 of the finite field GF(257) and stores these numbers
   in the table "exptab".  The corresponding logarithms to the base
   45 are stored in the table "logtab" */

  logtab[1]=0;
  exptab[0]=1;

  for(i=1;i<=255;i++)
  {
    exptab[i]=(45*exptab[i-1]) % 257;
    logtab[exptab[i]]=i;
  }

  exptab[128]=0;
  logtab[0]=128;
  exptab[0]=1;
}

set_rounds()
{
  int rounds;

  do
  {
    printf("Enter number of rounds (max 12): ");
    scanf("%d",&rounds);
  } while(rounds<1 || rounds>12);

  r=(unsigned char)rounds;
}

get_plaintext()
{
  int i1,i2,i3,i4,i5,i6,i7,i8;

  printf("Enter plaintext as 8 bytes (0-255 separated by spaces)\n");
  scanf("%d%d%d%d%d%d%d%d",&i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8);

  a1=(unsigned char)i1;
  a2=(unsigned char)i2;
  a3=(unsigned char)i3;
  a4=(unsigned char)i4;
  a5=(unsigned char)i5;
  a6=(unsigned char)i6;
  a7=(unsigned char)i7;
  a8=(unsigned char)i8;
}

get_key()
{
  int i1,i2,i3,i4,i5,i6,i7,i8;

  printf("Enter left half of key as 8 bytes (0-255 separated by spaces)\n");
  scanf("%d%d%d%d%d%d%d%d",&i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8);

  ka[0]=(unsigned char)i1;
  ka[1]=(unsigned char)i2;
  ka[2]=(unsigned char)i3;
  ka[3]=(unsigned char)i4;
  ka[4]=(unsigned char)i5;
  ka[5]=(unsigned char)i6;
  ka[6]=(unsigned char)i7;
  ka[7]=(unsigned char)i8;

  printf("Enter right half of key as 8 bytes (0-255 separated by spaces)\n");
  scanf("%d%d%d%d%d%d%d%d",&i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8);

  kb[0]=(unsigned char)i1;
  kb[1]=(unsigned char)i2;
  kb[2]=(unsigned char)i3;
  kb[3]=(unsigned char)i4;
  kb[4]=(unsigned char)i5;
  kb[5]=(unsigned char)i6;
  kb[6]=(unsigned char)i7;
  kb[7]=(unsigned char)i8;
}

key_schedule()
{
/* append a "parity byte" to the key k1 */

  ka[8]=ka[0]^ka[1]^ka[2]^ka[3]^ka[4]^ka[5]^ka[6]^ka[7];
  kb[8]=kb[0]^kb[1]^kb[2]^kb[3]^kb[4]^kb[5]^kb[6]^kb[7];

/* derive keys k1, k2, ... k2r+1 from input key ka, kb */

  for(j=0;j<8;j++)
    k[0][j]=kb[j];

/* each byte of the key ka is right rotated by 3 */

  for(j=0;j<9;j++)
    ka[j]=(ka[j]>>3) + (ka[j]<<5);

  for(i=1;i<=r;i++)
  {
  /* each byte of the keys ka and kb is left rotated by 6 */

    for(j=0;j<=8;j++)
    {
      ka[j]=(ka[j]<<6) + (ka[j]>>2);
      kb[j]=(kb[j]<<6) + (kb[j]>>2);
    }

  /* the key bias is added to give keys k2i-1 and k2i */

    for(j=1;j<=8;j++)
    {
      k[2*i-1][j-1]=ka[(j+2*i-2) % 9]+exptab[exptab[18*i+j]];
      k[2*i][j-1]=kb[(j+2*i-1) % 9]+exptab[exptab[18*i+9+j]];
    }
  }
}

encrypt()
{
  for(i=1;i<=r;i++)
  {
  /* Key 2i-1 is mixed bit and byte added  to the round input */

    a1=a1 ^ k[2*i-2][0];
    a2=a2 + k[2*i-2][1];
    a3=a3 + k[2*i-2][2];
    a4=a4 ^ k[2*i-2][3];
    a5=a5 ^ k[2*i-2][4];
    a6=a6 + k[2*i-2][5];
    a7=a7 + k[2*i-2][6];
    a8=a8 ^ k[2*i-2][7];

  /* The result now passes through the nonlinear layer */

    b1=exptab[a1];
    b2=logtab[a2];
    b3=logtab[a3];
    b4=exptab[a4];
    b5=exptab[a5];
    b6=logtab[a6];
    b7=logtab[a7];
    b8=exptab[a8];

  /* Key 2i is now mixed byte and bit added to the result */

    b1=b1 + k[2*i-1][0];
    b2=b2 ^ k[2*i-1][1];
    b3=b3 ^ k[2*i-1][2];
    b4=b4 + k[2*i-1][3];
    b5=b5 + k[2*i-1][4];
    b6=b6 ^ k[2*i-1][5];
    b7=b7 ^ k[2*i-1][6];
    b8=b8 + k[2*i-1][7];

  /* The result now enters the linear layer */

    mat1(b1,b2,&a1,&a2);
    mat1(b3,b4,&a3,&a4);
    mat1(b5,b6,&a5,&a6);
    mat1(b7,b8,&a7,&a8);

    mat1(a1,a3,&b1,&b2);
    mat1(a5,a7,&b3,&b4);
    mat1(a2,a4,&b5,&b6);
    mat1(a6,a8,&b7,&b8);

    mat1(b1,b3,&a1,&a2);
    mat1(b5,b7,&a3,&a4);
    mat1(b2,b4,&a5,&a6);
    mat1(b6,b8,&a7,&a8);

  /* The round is now completed! */

    printf("after round %d   %3d %3d %3d %3d %3d %3d %3d %3d\n",
	   (int)i,a1,a2,a3,a4,a5,a6,a7,a8);
  }

/* Key 2r+1 is now mixed bit and byte added to produce the final cryptogram */

  a1=a1 ^ k[2*r][0];
  a2=a2 + k[2*r][1];
  a3=a3 + k[2*r][2];
  a4=a4 ^ k[2*r][3];
  a5=a5 ^ k[2*r][4];
  a6=a6 + k[2*r][5];
  a7=a7 + k[2*r][6];
  a8=a8 ^ k[2*r][7];
}

main()
{
  init_tables();
  for(;;)
  {
    set_rounds();
    get_plaintext();
    get_key();

    printf("PLAINTEXT is    %3d %3d %3d %3d %3d %3d %3d %3d\n",
	   a1,a2,a3,a4,a5,a6,a7,a8);
    printf("KEY Ka IS       %3d %3d %3d %3d %3d %3d %3d %3d\n",
	   ka[0],ka[1],ka[2],ka[3],ka[4],ka[5],ka[6],ka[7]);
    printf("KEY Kb IS       %3d %3d %3d %3d %3d %3d %3d %3d\n",
	   kb[0],kb[1],kb[2],kb[3],kb[4],kb[5],kb[6],kb[7]);

    key_schedule();
    encrypt();

    printf("CRYPTOGRAM IS   %3d %3d %3d %3d %3d %3d %3d %3d\n\n",
	   a1,a2,a3,a4,a5,a6,a7,a8);
  }
}