No Subject

Hroller Anonymous Remailer hroller at c2.org
Thu Sep 14 09:12:58 PDT 1995


/* SAFER SK-64 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-64 (i.e., with the strengthened key
schedule of 64 bits.)
 
PLAINTEXT is        1   2   3   4   5   6   7   8
The KEY 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
CRYPTOGRAM is      21  27 255   2 173  17 191  45
 
PLAINTEXT is        1   2   3   4   5   6   7   8
The KEY is          1   2   3   4   5   6   7   8
after round 1     223  98 177 100  46 234  13 210
after round 2     182 246 230  93 158  14  48  89
after round 3      45 234 128 149  40 101  10 134
after round 4      30  17 249 236 158 120  69 100
after round 5       1 200 182 241   0 127 152 162
after round 6     144  85  94 214   5  38  65 150
CRYPTOGRAM is      95 206 155 162   5 132  56 199
*/


#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[21][8],k1[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 10): ");
    scanf("%d",&rounds);
  } while(rounds<1 || rounds>10);

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

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

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

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

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

  for(n=2;n<=(2*r)+1;n++)
  {
  /* each byte of the key k1 is left rotated by 3 */

    for(j=0;j<=8;j++)
      k1[j]=(k1[j]<<3) + (k1[j]>>5);

  /* the key bias is added here to the right rotated k1 */

    for(j=1;j<=8;j++)
      k[n-1][j-1]=k1[(j+n-2) % 9]+exptab[exptab[(9*n)+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("THE KEY IS      %3d %3d %3d %3d %3d %3d %3d %3d\n",
	   k[0][0],k[0][1],k[0][2],k[0][3],k[0][4],k[0][5],k[0][6],k[0][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);
  }
}






More information about the cypherpunks-legacy mailing list