/* 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); } }