Script started on Thu May 30 21:56:26 2002
[crandaj@node52-60
cryptanalysis]$ cat dpc.cpp
/******************************
*
* dpc.cpp
* Jedidiah Crandall, crandaj@erau.edu
* Generates plaintext/ciphertext pairs in a modified version
of S-DES
* which has three rounds and no initial or final permutation
* The plaintext/ciphertext pairs differ only in the first
bit
*
*******************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#define BYTE unsigned char
char key[25];
char *K1 = &key[0];
char *K2 = &key[8];
char *K3 = &key[16];
void SetKey(unsigned long int SetMe)
{
int i;
unsigned
long int n;
for (i = 0,
n = 0x800000; i <= 31; i++, n /= 2)
{
if (SetMe & n)
key[i] = '1';
else
key[i] = '0';
}
key[32] =
'\0';
}
int SBox0[4][4] =
{
{1, 0, 3, 2},
{3, 2, 1, 0},
{0, 2, 1, 3},
{3, 1, 3, 2}
};
int SBox1[4][4] =
{
{0, 1, 2, 3},
{2, 0, 1, 3},
{3, 0, 1, 0},
{2, 1, 0, 3}
};
BYTE BinaryToByte(char *Binary)
{
int n, i;
BYTE
ReturnMe = 0;
for (i = 0,
n = 128; i <= 7; i++, n /= 2)
{
switch(Binary[i])
{
case '0': break;
case '1':
ReturnMe += n;
break;
default:
puts("BinaryToByte
failed");
exit(0);
break;
}
}
return
ReturnMe;
}
void ByteToBinary(char *pBinary, BYTE TheByte)
{
int i;
BYTE n;
for (i = 0,
n = 0x80; i <= 7; i++, n >>= 1)
{
if (TheByte & n)
pBinary[i] = '1';
else
pBinary[i] = '0';
}
pBinary[8]
= '\0';
}
void S0(char *pDest, char *pSrc)
{
int Row =
(pSrc[0] - '0') * 2 + (pSrc[3] - '0');
int Col =
(pSrc[1] - '0') * 2 + (pSrc[2] - '0');
BYTE LookUp
= SBox0[Row][Col];
pDest[0] =
'0' + ((LookUp & 0x02) >> 1);
pDest[1] =
'0' + (LookUp & 0x01);
pDest[2] =
'\0';
}
void S1(char *pDest, char *pSrc)
{
int Row =
(pSrc[0] - '0') * 2 + (pSrc[3] - '0');
int Col =
(pSrc[1] - '0') * 2 + (pSrc[2] - '0');
BYTE LookUp
= SBox1[Row][Col];
pDest[0] =
'0' + ((LookUp & 0x02) >> 1);
pDest[1] =
'0' + (LookUp & 0x01);
pDest[2] =
'\0';
}
void P4(char *pDest, char *pS0Output, char *pS1Output)
{
pDest[0] =
pS0Output[1];
pDest[1] =
pS1Output[1];
pDest[2] =
pS1Output[0];
pDest[3] =
pS0Output[0];
pDest[4] =
'\0';
}
void XOR4(char *pDest, char *Operand1, char *Operand2)
{
int i;
BYTE a, b;
for (i = 0;
i <= 3; i++)
{
a = Operand1[i] - '0';
b = Operand2[i] - '0';
pDest[i] = '0' + (a ^ b);
}
pDest[4] =
'\0';
}
void EP(char *pDest, char *pSrc)
{
pDest[0] =
pSrc[3];
pDest[1] =
pSrc[0];
pDest[2] =
pSrc[1];
pDest[3] =
pSrc[2];
pDest[4] =
pSrc[1];
pDest[5] =
pSrc[2];
pDest[6] =
pSrc[3];
pDest[7] =
pSrc[0];
pDest[8] =
'\0';
}
void f(char *pDest, char *pSrc, char *Subkey)
{
char *pLeft
= &pSrc[0], *pRight = &pSrc[4];
char
OutputFromEP[9];
char
OutputFromXOR8[9];
BYTE
XOR8Result;
char
*pS0Input = &OutputFromXOR8[0];
char
*pS1Input = &OutputFromXOR8[4];
char
S0Output[3];
char
S1Output[3];
char
P4Output[5];
char
XOR4Output[5];
EP(OutputFromEP,
pRight);
XOR8Result
= BinaryToByte(OutputFromEP) ^ BinaryToByte(Subkey);
ByteToBinary(OutputFromXOR8,
XOR8Result);
S0(S0Output,
pS0Input);
S1(S1Output,
pS1Input);
P4(P4Output,
S0Output, S1Output);
XOR4(XOR4Output,
P4Output, pLeft);
memcpy(pDest,
XOR4Output, 4);
memcpy(&pDest[4],
pRight, 4);
pDest[8] =
'\0';
}
void SW(char *pDest, char *pSrc)
{
pDest[0] =
pSrc[4];
pDest[1] =
pSrc[5];
pDest[2] =
pSrc[6];
pDest[3] =
pSrc[7];
pDest[4] =
pSrc[0];
pDest[5] =
pSrc[1];
pDest[6] =
pSrc[2];
pDest[7] =
pSrc[3];
pDest[8] =
'\0';
}
BYTE SDES(BYTE nPlaintext)
{
BYTE
nCiphertext;
char
Plaintext[9];
char
OutOffK1[9];
char
IntofK2[9];
char
OutOffK2[9];
char
IntofK3[9];
char
OutOffK3[9];
ByteToBinary(Plaintext,
nPlaintext);
f(OutOffK1,
Plaintext, K1);
SW(IntofK2,
OutOffK1);
f(OutOffK2,
IntofK2, K2);
SW(IntofK3,
OutOffK2);
f(OutOffK3,
IntofK3, K3);
nCiphertext
= BinaryToByte(OutOffK3);
return
nCiphertext;
}
int main()
{
unsigned
int DidItAlready[128];
unsigned
int Plaintext;
unsigned
int NumberDone;
unsigned
long int TheKey;
memset(DidItAlready,
0, 128 * sizeof(unsigned int));
fprintf(stderr,
"You must enter a hexadecimal key, such as 22B8FA\n");
fprintf(stderr,
"The last two hex digits (FA) are the 8-bit subkey for the last
round.\n");
fprintf(stderr,
"Please enter the key you'd like to use:\n");
scanf("%x",
&TheKey);
SetKey(TheKey);
srand(2233);
NumberDone
= 0;
while
(NumberDone < 25)
{
Plaintext = rand() % 128;
if (!DidItAlready[Plaintext])
{
DidItAlready[Plaintext] = 1;
printf("%d\t%d\n",
Plaintext, SDES(Plaintext));
Plaintext |= 0x80;
printf("%d\t%d\n",
Plaintext, SDES(Plaintext));
NumberDone++;
}
}
printf("\n");
return 0;
}
[crandaj@node52-60
cryptanalysis]$ cat diff.cpp
/**********************************************
* diff.cpp
* Jedidiah Crandall, crandaj@erau.edu
* Does differential cryptanalysis on a modified version of
S-DES which
* uses three rounds instead of two, uses independent
subkeys, and has
* no initial or final permutation
***********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BYTE unsigned char
int SBox0[4][4] =
{
{1, 0, 3, 2},
{3, 2, 1, 0},
{0, 2, 1, 3},
{3, 1, 3, 2}
};
int SBox1[4][4] =
{
{0, 1, 2, 3},
{2, 0, 1, 3},
{3, 0, 1, 0},
{2, 1, 0, 3}
};
BYTE BinaryToByte(char *Binary)
{
int n, i;
BYTE
ReturnMe = 0;
for (i = 0,
n = 128; i <= 7; i++, n /= 2)
{
switch(Binary[i])
{
case '0': break;
case '1':
ReturnMe += n;
break;
default:
puts("BinaryToByte
failed");
exit(0);
break;
}
}
return
ReturnMe;
}
void ByteToBinary(char *pBinary, BYTE TheByte)
{
int i;
BYTE n;
for (i = 0,
n = 0x80; i <= 7; i++, n >>= 1)
{
if (TheByte & n)
pBinary[i] = '1';
else
pBinary[i] = '0';
}
pBinary[8]
= '\0';
}
void EP(char *pDest, char *pSrc)
{
pDest[0] =
pSrc[3];
pDest[1] =
pSrc[0];
pDest[2] =
pSrc[1];
pDest[3] =
pSrc[2];
pDest[4] =
pSrc[1];
pDest[5] =
pSrc[2];
pDest[6] =
pSrc[3];
pDest[7] =
pSrc[0];
pDest[8] =
'\0';
}
void S0(char *pDest, char *pSrc)
{
int Row =
(pSrc[0] - '0') * 2 + (pSrc[3] - '0');
int Col =
(pSrc[1] - '0') * 2 + (pSrc[2] - '0');
BYTE LookUp
= SBox0[Row][Col];
pDest[0] =
'0' + ((LookUp & 0x02) >> 1);
pDest[1] =
'0' + (LookUp & 0x01);
pDest[2] =
'\0';
}
void S1(char *pDest, char *pSrc)
{
int Row =
(pSrc[0] - '0') * 2 + (pSrc[3] - '0');
int Col =
(pSrc[1] - '0') * 2 + (pSrc[2] - '0');
BYTE LookUp
= SBox1[Row][Col];
pDest[0] =
'0' + ((LookUp & 0x02) >> 1);
pDest[1] =
'0' + (LookUp & 0x01);
pDest[2] =
'\0';
}
void P4(char *pDest, char *pS0Output, char *pS1Output)
{
pDest[0] =
pS0Output[1];
pDest[1] =
pS1Output[1];
pDest[2] =
pS1Output[0];
pDest[3] =
pS0Output[0];
pDest[4] =
'\0';
}
void P4Inverse(char *pDest, char *pSrc)
{
pDest[0] =
pSrc[3];
pDest[1] =
pSrc[0];
pDest[2] =
pSrc[2];
pDest[3] =
pSrc[1];
pDest[4] =
'\0';
}
void XOR4(char *pDest, char *Operand1, char *Operand2)
{
int i;
BYTE a, b;
for (i = 0;
i <= 3; i++)
{
a = Operand1[i] - '0';
b = Operand2[i] - '0';
pDest[i] = '0' + (a ^ b);
}
pDest[4] =
'\0';
}
struct DiffPair
{
unsigned
int Plaintext0;
unsigned
int Ciphertext0;
unsigned
int Plaintext1;
unsigned
int Ciphertext1;
};
DiffPair ThePairs[50];
int main()
{
unsigned
int Loop;
char
sPlaintext[9];
char
sCiphertext[9];
unsigned
int Subkey;
unsigned
int TryPair;
unsigned
int Bad;
unsigned
int RightHalf0, RightHalf1;
unsigned
int LeftHalf0, LeftHalf1;
char
sRightHalf0[9], sRightHalf1[9];
char sEPOutput0[9],
sEPOutput1[9];
unsigned
int EPOutput0, EPOutput1;
unsigned
int SBox0Input0, SBox0Input1;
unsigned
int SBox1Input0, SBox1Input1;
char
sSBox0Input0[9], sSBox0Input1[9];
char
sSBox1Input0[9], sSBox1Input1[9];
char
sSBoxOutput0[9], sSBoxOutput1[9];
unsigned
int ActualDifference;
unsigned
int ExpectedDifference;
char
sExpectedDifference[9];
char
sP4InverseOutput[9];
// First,
read in about 25 plaintext/ciphertext pairs
// we could
probably get away with less, but 25 is not a bad number
for (Loop =
0; Loop <= 24; Loop++)
{
scanf("%s\t%s",
sPlaintext, sCiphertext);
ThePairs[Loop].Plaintext0 =
atoi(sPlaintext);
ThePairs[Loop].Ciphertext0 =
atoi(sCiphertext);
scanf("%s\t%s",
sPlaintext, sCiphertext);
ThePairs[Loop].Plaintext1 =
atoi(sPlaintext);
ThePairs[Loop].Ciphertext1 =
atoi(sCiphertext);
}
// This
prints a few of the ciphertext/plaintext pairs in binary
// so you
can see what they look like
for (Loop =
10; Loop <= 12; Loop++)
{
ByteToBinary(sPlaintext,
ThePairs[Loop].Plaintext0);
ByteToBinary(sCiphertext,
ThePairs[Loop].Ciphertext0);
printf("%s -> %s\n",
sPlaintext, sCiphertext);
ByteToBinary(sPlaintext,
ThePairs[Loop].Plaintext1);
ByteToBinary(sCiphertext,
ThePairs[Loop].Ciphertext1);
printf("%s -> %s\n",
sPlaintext, sCiphertext);
}
// Now try
every possible subkey
for (Subkey
= 0; Subkey <= 0xFF; Subkey++)
{
Bad = 0;
for (TryPair = 0; TryPair <= 24;
TryPair++)
{
// The first thing we have to do is
take the right halves of the
// ciphertexts in the pair and put
them back through E/P and everything
// to find an ACTUAL XOR difference
of the S-box output for this subkey
RightHalf0 =
ThePairs[TryPair].Ciphertext0 & 0x0f;
RightHalf1 =
ThePairs[TryPair].Ciphertext1 & 0x0f;
ByteToBinary(sRightHalf0,
RightHalf0);
ByteToBinary(sRightHalf1,
RightHalf1);
EP(sEPOutput0, &sRightHalf0[4]);
EP(sEPOutput1, &sRightHalf1[4]);
EPOutput0 = BinaryToByte(sEPOutput0);
EPOutput1 =
BinaryToByte(sEPOutput1);
EPOutput0 ^= Subkey;
EPOutput1 ^= Subkey;
SBox0Input0 = (EPOutput0 & 0xf0)
>> 4;
SBox1Input0 = EPOutput0 & 0x0f;
SBox0Input1 = (EPOutput1 & 0xf0)
>> 4;
SBox1Input1 = EPOutput1 & 0x0f;
ByteToBinary(sSBox0Input0,
SBox0Input0);
ByteToBinary(sSBox1Input0,
SBox1Input0);
ByteToBinary(sSBox0Input1,
SBox0Input1);
ByteToBinary(sSBox1Input1,
SBox1Input1);
memset(sSBoxOutput0, '0', 4);
memset(sSBoxOutput1, '0', 4);
S0(&sSBoxOutput0[4],
&sSBox0Input0[4]);
S1(&sSBoxOutput0[6],
&sSBox1Input0[4]);
S0(&sSBoxOutput1[4],
&sSBox0Input1[4]);
S1(&sSBoxOutput1[6],
&sSBox1Input1[4]);
ActualDifference =
BinaryToByte(sSBoxOutput0) ^ BinaryToByte(sSBoxOutput1);
// Then we take the left half of the
two ciphertexts in the pair and
// use them to trace back to an
EXPECTED XOR difference
LeftHalf0 =
(ThePairs[TryPair].Ciphertext0 & 0xf0) >> 4;
LeftHalf1 =
(ThePairs[TryPair].Ciphertext1 & 0xf0) >> 4;
ExpectedDifference = LeftHalf0 ^
LeftHalf1;
ExpectedDifference ^= 0x08;
ByteToBinary(sExpectedDifference,
ExpectedDifference);
memset(sP4InverseOutput, '0', 4);
P4Inverse(&sP4InverseOutput[4],
&sExpectedDifference[4]);
ExpectedDifference =
BinaryToByte(sP4InverseOutput);
// If it just so happens that what
we got wasn't what we were expecting
// then this probably isn't the
right subkey
if (ActualDifference !=
ExpectedDifference)
Bad++;
}
if (Bad == 0)
printf("K3 might be
0x%02x?\n", Subkey);
}
return 0;
}
[crandaj@node52-60
cryptanalysis]$ ./dpc > dpcout.txt
You must enter a hexadecimal key, such as 22B8FA
The last two hex digits (FA) are the 8-bit subkey for the
last round.
Please enter the key you'd like to use:
ba48c2
[crandaj@node52-60
cryptanalysis]$ cat dpcout.txt
77 232
205 127
72 208
200 204
100 107
228 29
82 227
210 0
39 173
167 8
63 26
191 77
40 111
168 230
53 252
181 137
96 149
224 146
87 89
215 176
34 235
162 157
103 181
231 86
58 200
186 155
56 154
184 205
1 102
129 239
127 182
255 131
90 3
218 54
61 57
189 101
50 206
178 123
20 214
148 53
86 47
214 25
118 254
246 98
81 13
209 168
114 160
242 167
37 74
165 108
[crandaj@node52-60
cryptanalysis]$ cat dpcout.txt |
./diff
00100010 -> 11101011
10100010 -> 10011101
01100111 -> 10110101
11100111 -> 01010110
00111010 -> 11001000
10111010 -> 10011011
K3 might be 0xc2?
[crandaj@node52-60
cryptanalysis]$ exit
exit
Script done on Thu May 30 21:57:18 2002