Anda di halaman 1dari 26

1.

0 Introduction
To secure data such as sending messages through emails, the original message known as
plaintext must be converted into a ciphertext. Ciphertext is a meaningless message which
can consists of alphabets, numbers and symbols mixed in a not orderly manner. To change
the ciphertext into the original plaintext, decryption is used. For encryption and decryption to
happen a key which must be the same for both process to happen, is used.

Figure 1. Operation for encryption and decryption.

Encryption and decryption is based on various types of codings such as Caesar Cipher (the
simplest and oldest form), RSA and Advanced Encryption Standard (AES). AES was used in
the codings and is used in 128 bit forms making it a very secure form of encrypting and
decrypting data. However, if the data stored is more secure, the greater the complexity of the
codings used.

Arrays were frequently used in the codings to store characters consisting of alphabets,
numbers and symbols.

Function Purpose

strlen() Count length of string.

strcpy() Copy string to another string.

strcat() Joins one string to another string.

strcmp() Compares two strings.


Table 1. Some library string functions were used in the coding.

1.1 Boolean expression and logical operators:

Figure 2. Boolean chart

1
Operator Description Example

&& AND (string[i] >= 'a' && string[i] <= 'z'

|| OR (string[i] >= 'A' && string[i] <= 'Z') || isdigit(string[i])

! NOT if (ch != '0')


Table 2. Logical Operators.

Logical operators were frequently used with the Boolean expressions to make decisions in
the codings.

Void functions are used where they do not return a value but can be used for calculation.
The type of the value can be returned.

Syntax for void function.

1.2 If statement:
Figure 2. If statement flowchart.

The if statement checks the expression


first before it proceeds to the body of
another statement. If the statement is true,
the body will be executed and followed by
the next statement.

2
1.3 For loop
Figure 3. Flowchart of for loop.

Syntax of for loop:


For (initialStatement; testExpression;
updateStatement)
{
// codes
}

3
Figure 4. American Standard Code for Information Technology (ASCII) Table.

Unsigned integers were used as they only hold positive integers values. It must not hold
negative values such as in signed int (hold positive and negative values). As the ASCII table
only consists of values from 0 to 127, negative values must not be read. But in decryption,
signed variable must be used to accept negative and positive values.

In Caesar Cipher (used in the alternative coding), if the secret key is let’s say; 5. The entered
string will have an addition of ASCII value of 5 from its respective decimal number for
encryption. If the plaintext is: “hello”, the ciphertext will become: “mjqqt”. Referring to the
ASCII table the numbers consisting of the words “hello” are: 104, 101, 108, 108, 111. After
shifting 5, the numbers are 109, 106, 113, 113, 116 and it corresponds to the letters: “mjqqt”.

However, if the key is a large number, problems will emerge as invalid results will appear.
These invalid results are symbols that are not found in the ASCII table. To avoid this, a while
loop must be used in the expression where the maximum alphabet or number is stated as
shown in line 36, 45, 54, 70, 79, 88. This can be manually calculated using the formula:

e(x) = (x+k) mod 26 … encryption


e(x) = (x-k) mod 26 … decryption
Where k is the key and x is the decimal value of the character in the ASCII table.
The only difference between the two formulas is the operator of ‘+’ and ‘-’. This can also be
seen in the codings used such as in line 32 and line 70. It can be said that Caesar Cipher
encryption and decryption is adding or subtracting the key respectively; the opposite of one
another. An example on how the formula is used is shown below:

e(x) = (104+107) mod 26 = 211 mod 26 = 211/26 (has remainder of 3)


Since this formula is for encryption, 104+3=107. Referring to the ASCII table, the decimal
value of 107 is the character ‘k’. This process is the same for the other characters in the
plaintext as shown below:

The plaintext: how are you 345


The ciphertext: krz duh brx 012

2.0 Results
2.1 AES inspired encryption program

Figure 5. Menu of program.

Figure 6. Error output example.

Figure 7. Successful encryption.


Figure 8. Successful decryption.

Figure 9. Penetration testing program.

Figure 10. Penetration testing output.

Figure 11. Key found.


2.2 Caesar cipher encryption algorithm

Figure 12. Encryption of message. (Alternative coding)

Figure 13. Decryption of message. (Alternative coding)

Figure 14. Alternative coding pentesting.


Figure 15. All 26 results of caesar cipher which includes 25 combinations and original encrypted
message.

3.0 Discussion
A symmetric encryption is used instead of an asymmetric encryption in this assignment due
to its simplicity in encrypting a message by using a key instead of using two keys. The
difference between symmetric key and asymmetric key is in symmetric encryption, the same
key is used to decrypt and encrypt a message. For asymmetric encryption, two keys are
used, a public key and a private key. A public key is used to encrypt a particular message
whereas a private key is used to decrypt the message. Asymmetric encryption is mostly
used in Transport layer security whereby the server’s public key is used to encrypt the partial
master key (a key used in symmetric encryption), the encrypted partial master key (a key
which is encrypted by using the server’s public key) is then sent to the server. The server
then uses its private key to decrypt the partial master key. A master key is then formed which
uses AES and is then used to transmit encrypted messages to and from the server to the
client instead of using asymmetric encryption because it is faster. The usage of modern
encryption algorithm such as AES which stands for Advanced Encryption Standard is due to
its robustness against brute force attacks. The standard comprises of three block ciphers,
AES-128, AES-192 and AES-256, each successive block cipher is better compared to the
previous block cipher. Each of the ciphers has a key size of 128-bit, 192-bit and 256-bit
respectively. AES ciphers are now used extensively and worldwide after the Triple-DES
cipher known as Triple Data Encryption Algorithm (TDEA or Tripe DEA) which is the
application of the DES cipher known as Data Encryption Standard three times is termed as
inefficient due to its usage of high computational power. In this assignment, the Advanced
Encryption Standard is used as an inspiration to encrypt messages to and from a source.
The full source code of this assignment is attached in the Appendix section. The source code
will be explained based on user interaction and its program structure.

FILE * text; //FILE pointer object named as text, to work with streams
char message[226], converted[226], key[18], characters[] = "!@#$%^&*()_+-={}[]<>|:/",
selection[3], temp[2], c;
unsigned char state[4][4], key_array[4][4], key_transpose_array[4][4], key_rotate_array[4][4];
int position_k = 0, pos = 0, dec = 0, index = 0, shift = 0;

FILE is declared as a file pointer object to text. The data type known as char is default as a
signed char which has a value of -127 to 127 in Visual Studio. The message variable is used
to contain the message between the encryption and decryption process. The converted
variable is used to hold the converted characters from hexadecimals during the decryption
process. The key variable is used to hold the key input by the user. The characters variable
is used to hold random characters which will be used during the key generation process. The
selection variable is used to hold the user input selection. The temp variable is used to hold
two values which are combined as hexadecimals and will be converted to a specific
character by keying it into the c variable. The data type unsigned char has a range from 0 to
255. The state variable is used to hold the intermediate state during the encryption and
decryption process. The key_array variable is used to hold the generated key, the
key_transpose_array variable is used to hold the transposed generated key and the
key_rotate variable is used to hold the rotated transposed key. The position_k variable is the
index position during the key generation process. The pos variable is the index position
during the message reading process. The dec variable is the index position on the
characters variable and the shift variable is used to hold the value of the first number from
the left of the key variable.

int main(){
printf("1. Encryption\n2. Decryption\n\n0. Exit\n\n");
while (true) {
printf(">>>>");
if (fgets_a(selection, 3, stdin, 2) != 1) {
if (!(strcmp(selection, "1") == 0 || strcmp(selection, "2") == 0 ||
strcmp(selection, "0") == 0)) {
printf("Invalid input\n");
}
if (strcmp(selection, "1") == 0) {
encryption();
}
if (strcmp(selection, "2") == 0){
decryption();
}
if (strcmp(selection, "0") == 0) {
break;
}
}
reset(); //reset function that resets variable values
}
return 0;
}

The code above is the menu of the program. The function fgets_a function is a modified
version of the fgets function. In this scenario, it returns 1 when size of user input is more
than the message variable size - 2 and when user input is not a number. The strcmp function
is used to compare the user input selection variable with a string literal which is “1”, “2” and
“0”. If user input is 1, the encryption process will begin, if user input is 2, the decryption
process will begin. Is user input is 0, the program will exit. The reset function is used to reset
variables such as message, key, position_k, dec and pos to its original state. If user input is
1 the following code will be executed.

void encryption() {
fopen_s(&text, "text.txt", "w+"); //creates text.txt, if it exists, its contents are cleared
printf("Type your message (max 112 characters consisting of alphabets, numbers, '!?,.'
and whitespaces only) :\n");
if (fgets_a(message, 114, stdin, 0) == 1) {
fclose(text); //closes text.txt
return;
}
printf("Type the symmetric key (16 numbers only) :");
if (fgets_a(key, 18, stdin, 2) == 1) {
fclose(text); //closes text.txt
return;
}
cipher(0); //sets the cipher function to decrypt message
fclose(text); //closes text.txt
printf("\n");
return;
}

The code above creates a text.txt file for reading and writing, if the files exists, the contents
within the file are cleared. If user input for the message variable is more than 112 characters,
it returns to the main function. The same applies for the key variable if it is more than 16
characters. If both fgets_a function returns 0, the cipher function is called. If the value
supplied into the cipher function is an argument of 0, it is switched to the encryption process.
If the value supplied into the cipher function is an argument of 1, it is switched to the
decryption process. After the cipher function is completed, the file text.txt is closed and the
encryption function returns to the main function.

void cipher(int junction) {


createkey(key); //create the 128-bit AES inspired key
transpose_key(); //transpose the original key
rotate_key(); //rotate the transposed key
if (junction == 0) {
check_m_length(); //adds padding if message length is not divisible by 16
encrypt(message); //encrypt
}
if (junction == 1) {
hex_to_char();
decrypt(message); //decrypt
}
clear_key(); //clears key arrays
}

The cipher function as shown above creates a 128-bit key, it then transposes the key. The
transposed key is then rotated and stored in the key_rotate_array variable. The
check_m_length function adds padding to the message with character ‘ ‘, commonly known
as a space to the message if the modulus of 16 of the length of the message is not 0. The
encrypt function encrypts the message. During the decryption process, the hex_to_char
function changes hexadecimals to characters by adding two characters from the user input
and changing it to a character which is stored in the c variable. The character within the c
variable is added to the converted variable based on the index within the hex_to_char
variable. The decrypt function then decrypts the message based on the converted variable.
The clear key function resets key arrays to default after a session.

void createkey(char * key_in) { //set up a 128-bit key


for (size_t j = 0; j < 4; j++) {
for (size_t k = 0; k < 4; k++) {
if (key_in[position_k] == '\0') { //if null terminator is found from key input, start
to add padding
for (size_t d = k; d < 4; d++) {
dec++;
key_array[j][d] = characters[dec]; //characters based on the
index position of dec will be added to the key_array
}
for (size_t m = j + 1; m < 4; m++){ //continue add padding to the key
array from characters
for (size_t l = 0; l < 4; l++){
dec++;
key_array[m][l] = characters[dec];
}
}
return;
}
chartodec(key_in, j, k); //function to change a character to a decimal
}
}
return;
}

The createkey function above adds key input and stores it into a 4 by 4 matrix, which has 4
rows and 4 columns. Since the key variable only stores characters from ‘0’ to ‘9’, therefore
the chartodec function changes the characters to decimals by subtracting the ASCII value of
the specified character with the ASCII value of ‘0’. The shift variable is used within the
chartodec function to store the first value from the left of the user defined key input. The key
generation process continues until a null terminator which signifies the end of the key is
found. In an instance whereby the key array is not fully filled, padding is added to the key
array based on the symbols within the characters variable pointed by the variable dec until
the key is fully generated.

3.1 Encryption process


void encrypt(char * text_in) {
while (pos != strlen(text_in)) { //XOR Logic
array4by4(text_in); //pack a portion of the string into a 4x4 matrix
for (size_t b = 0; b < 4; b++) {
for (size_t j = 0; j < 4; j++) {
add_key(b, j); //adding key to state operation
}
}
clear_state(); //clears the state after each work session
}
}

The encrypt function above encrypts the message by first packing the message to 4 by 4
array, it then starts to add key arrays to the 4 by 4 matrix, after each session, the function
clear_state is called whereby it clears the state array after each work session.

void add_key(size_t row, size_t column) {


state[row][column] += shift; //shift the value of the state
state[row][column] ^= key_array[row][column]; //add original key
state[row][column] += shift; //shift the value of the state
for (size_t rounds = 0; rounds < 2; rounds++) { //do the following operations twice
state[row][column] = getSBoxValue(state[row][column]); //map the state array to
something else
state[row][column] ^= key_array[row][column]; //add original key again
state[row][column] ^= key_transpose_array[row][column]; //add transposed original
key
state[row][column] ^= key_rotate_array[row][column]; //add rotated transposed key
}

fprintf(text, "%02X", state[row][column]);


printf("%02X", state[row][column]);
}

The add_key function as shown in the above first adds the ASCII value of the state with the
shift variable, then XOR with key_array, adds the ASCII value of the current state with the
shift variable, then undergoes two rounds of state array mapping, XOR with key_ array, XOR
with key_transpose_array, XOR with key_rotate_array and finally prints out the state value in
hexadecimals on the console screen and in a text file. The getSBoxValue function maps the
state to a different character based on the ASCII value of the current state and the Sbox
table as shown below.
Figure 16. Sbox table.

3.2 Decryption process


The add_key_reversed function is similar to the add_key function but in reversed order and
is used during the decryption process. The full code for the function is as shown below.

void add_key_reversed(size_t row, size_t column) {


for (size_t rounds = 0; rounds < 2; rounds++) { //do the following operations twice
state[row][column] ^= key_rotate_array[row][column]; //add rotated transposed key
state[row][column] ^= key_transpose_array[row][column]; //add transposed original
key
state[row][column] ^= key_array[row][column]; //add original key
state[row][column] = getSBoxInvert(state[row][column]); //map the state array to
previous array
}
state[row][column] -= shift; //unshift the value of the state
state[row][column] ^= key_array[row][column]; //finally add the original key
state[row][column] -= shift; //unshift the value of the state
fprintf(text, "%c", state[row][column]);
printf("%c", state[row][column]);
}

The getSBoxInvert function is the inverse of the getSBoxValue function and is used to map
the array to the previous array based on the ASCII value of the current state and the table as
inverted Sbox table as shown below.
Figure 16. Inverted Sbox table.

3.3 Penetration testing


In a real world scenario, it is vital to test the strength of the encryption algorithm and test its
strength against brute force attacks or be on the side of the ‘red team’. Since the key
supplied by user is of only 3 digit in length, the program is highly vulnerable to brute force
attacks as shown in the Results section of this report. The source code for the brute force
program is inefficient and is only capable of brute forcing a 3 digit combination key. Another
important factor is the ability of the encryption algorithm to mask the message based on the
supplied key so that it does not reveal some parts of the words when a different key is
supplied, this can be seen through the text as shown in the results section.

4.0 Appendix
// assignment_2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>
#include <ctype.h>

FILE * text; //FILE pointer object named as text, to work with streams
char message[226], converted[226], key[18], characters[] = "!@#$%^&*()_+-={}[]<>|:/",
selection[3], temp[2], c;
unsigned char state[4][4], key_array[4][4], key_transpose_array[4][4], key_rotate_array[4][4];
int position_k = 0, pos = 0, dec = 0, index = 0, shift = 0;
/*
----------------
Global Variables
----------------
message character array is obtained from input stream, is used to hold either plaintext or
encrypted message
converted character array is used to hold characters converted from hexadecimals during
the decryption process
key is obtained from input stream
characters are used for symbol selection during the key generation process
selection is used for input selection
temp is used to hold hexadecimals before conversion
c is the converted character from hexadecimals, hexadecimals are a numeral system with
base 16, starting from 0-9 (0-10 in decimals) and then A-F (11-16 in decimals)
state is the intermediate state of the array during encryption or decryption
key_array is the 128-bit key in array form
key_transpose_array is the transposed original key
key_rotate_array is the rotated transposed key
position_k is the index position during key generation
pos is the index position during message reading
dec is the index position on the characters variable
index is the position on the converted variable
shift is the value of the first number from the left of the key
*/

int getSBoxValue(int num){ //pass the state array through the following table which maps to
something else
int sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B
C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7,
0xab, 0x76, //0
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4,
0x72, 0xc0, //1
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8,
0x31, 0x15, //2
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb,
0x27, 0xb2, 0x75, //3
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
0xe3, 0x2f, 0x84, //4
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c,
0x58, 0xcf, //5
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
0x9f, 0xa8, //6
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff,
0xf3, 0xd2, //7
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d,
0x19, 0x73, //8
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde,
0x5e, 0x0b, 0xdb, //9
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91,
0x95, 0xe4, 0x79, //A
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a,
0xae, 0x08, //B
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd,
0x8b, 0x8a, //C
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
0xc1, 0x1d, 0x9e, //D
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55,
0x28, 0xdf, //E
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54,
0xbb, 0x16 }; //F
return sbox[num];
}

int getSBoxInvert(int num){ //reverse mapping of state array


int rsbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3,
0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde,
0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa,
0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d,
0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,
0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7,
0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3,
0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13,
0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4,
0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75,
0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18,
0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd,
0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27,
0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9,
0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53,
0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
0x21, 0x0c, 0x7d };
return rsbox[num];
}

void clear() {
while (getchar() != '\n'); //executes getchar() from beggining to '\n', used to clear input
stream
}

int fgets_a(char * string, unsigned int num, FILE * Stream, int junction) { //limit string, check
for alphabet, numbers and whitespaces
fgets(string, num, Stream);
string[strcspn(string, "\n")] = 0;
if (strlen(string) > num - 2) {
printf("Invalid input\n");
clear();
return 1;
}
if (strcmp(string, "") == 0) {
printf("Invalid input\n");
return 1;
}
if (junction == 0) { //used for reading input messages
for (size_t i = 0; i < strlen(string); i++) {
if (!((string[i] >= 'a' && string[i] <= 'z') || (string[i] >= 'A' && string[i] <= 'Z') ||
isdigit(string[i]) || string[i] == ' ' || string[i] == '!' ||
string[i] == '.' || string[i] == ',' || string[i] == '?' )) {
printf("Invalid input\n");
return 1;
}
}
}
if (junction == 1) { //used only for reading encrypted messages
for (size_t i = 0; i < strlen(string); i++) {
if (!((string[i] >= 'A' && string[i] <= 'Z') || isdigit(string[i]))) {
printf("Invalid input\n");
return 1;
}
}
}
if (junction == 2) { //used to read numbers
for (size_t i = 0; i < strlen(string); i++){
if (!isdigit(string[i])) {
printf("Invalid input\n");
return 1;
}
}
}
return 0;
}

void clear_state() { //Empties the elements in a state


for (size_t i = 0; i < 4; i++) {
for (size_t j = 0; j < 4; j++) {
state[i][j] = 0;
}
}
}

void chartodec(char * key_in, size_t row, size_t column) {


/*changes characters to decimals during the key generation process,
is used to define index position dec*/
char ch = key_in[position_k];
if (ch != '0') {
dec = ch - '0'; //minus ASCII value of '0'
if (position_k == 0) {
shift = dec;
}
dec++;
key_array[row][column] = characters[dec];
position_k++;
return;
}
key_array[row][column] = characters[0];
position_k++;
return;
}

void createkey(char * key_in) { //set up a 128-bit key


for (size_t j = 0; j < 4; j++) {
for (size_t k = 0; k < 4; k++) {
if (key_in[position_k] == '\0') { //if null terminator is found from key input, start
to add padding
for (size_t d = k; d < 4; d++) {
dec++;
key_array[j][d] = characters[dec]; //characters based on the
index position of dec will be added to the key_array
}
for (size_t m = j + 1; m < 4; m++){ //continue add padding to the key
array from characters
for (size_t l = 0; l < 4; l++){
dec++;
key_array[m][l] = characters[dec];
}
}
return;
}
chartodec(key_in, j, k); //function to change a character to a decimal
}
}
return;
}

void transpose_key() {
for (size_t i = 0; i < 4; i++){ //move rows of the key to columns of the key
for (size_t j = 0; j < 4; j++){
key_transpose_array[j][i] = key_array[i][j];
}
}
}

void rotate_key() {
for (size_t i = 0; i < 4; i++){ //rotate the transposed key, move each column on each row to
the left once
key_rotate_array[i][3] = key_transpose_array[i][0];
key_rotate_array[i][0] = key_transpose_array[i][1];
key_rotate_array[i][1] = key_transpose_array[i][2];
key_rotate_array[i][2] = key_transpose_array[i][3];
}
}

void array4by4(char * text_in) { //fills up the 4x4 matrix with characters obtained from the
message input
for (size_t j = 0; j < 4; j++) {
for (size_t k = 0; k < 4; k++) {
state[j][k] = text_in[pos];
pos++;
}
}
return;
}

void add_key(size_t row, size_t column) {


state[row][column] += shift; //shift the value of the state
state[row][column] ^= key_array[row][column]; //add original key
state[row][column] += shift; //shift the value of the state
for (size_t rounds = 0; rounds < 2; rounds++) { //do the following operations twice
state[row][column] = getSBoxValue(state[row][column]); //map the state array to
something else
state[row][column] ^= key_array[row][column]; //add original key again
state[row][column] ^= key_transpose_array[row][column]; //add transposed original
key
state[row][column] ^= key_rotate_array[row][column]; //add rotated transposed key
}

fprintf(text, "%02X", state[row][column]);


printf("%02X", state[row][column]);
}
void add_key_reversed(size_t row, size_t column) {
for (size_t rounds = 0; rounds < 2; rounds++) { //do the following operations twice
state[row][column] ^= key_rotate_array[row][column]; //add rotated transposed key
state[row][column] ^= key_transpose_array[row][column]; //add transposed original
key
state[row][column] ^= key_array[row][column]; //add original key
state[row][column] = getSBoxInvert(state[row][column]); //map the state array to
previous array
}
state[row][column] -= shift; //unshift the value of the state
state[row][column] ^= key_array[row][column]; //finally add the original key
state[row][column] -= shift; //unshift the value of the state
fprintf(text, "%c", state[row][column]);
printf("%c", state[row][column]);
}

void encrypt(char * text_in) {


while (pos != strlen(text_in)) { //XOR Logic
array4by4(text_in); //pack a portion of the string into a 4x4 matrix
for (size_t b = 0; b < 4; b++) {
for (size_t j = 0; j < 4; j++) {
add_key(b, j); //adding key to state operation
}
}
clear_state(); //clears the state after each work session
}
}

void decrypt(char * text_in) {


while (pos != strlen(text_in)) { //XOR Logic
array4by4(text_in); //pack a portion of the string into a 4x4 matrix
for (size_t a = 0; a < 4; a++) {
for (size_t j = 0; j < 4; j++) {
add_key_reversed(a, j); //adding key in reversed order to state
operation
}
}
clear_state(); //clears the state after each work session
}
}

void hex_to_char() { //this function is used to change hexadecimals to characters


index = 0;
while (message[pos] != '\0'){ //loop continues if null terminator is not found in input
message
for (size_t z = 0; z < 2; z++){
temp[z] = message[pos];
pos++;
}
sscanf_s(temp, "%02X", &c);
converted[index] = c;
index++;
}
pos = 0;
memset(message, 0, 202); //adds 0 from message[0] up to message[201]
strcpy_s(message, converted);
memset(converted, 0, 202); //adds 0 from converted[0] to converted[201]

void clear_key() { //clears key arrays


for (size_t i = 0; i < 4; i++){
for (size_t j = 0; j < 4; j++){
key_array[i][j] = 0;
key_transpose_array[i][j] = 0;
key_rotate_array[i][j] = 0;
}
}
}

void check_m_length() {
for (size_t i = strlen(message); strlen(message) % 16 != 0; i++){
message[i] = ' ';
}
}

void cipher(int junction) {


createkey(key); //create the 128-bit AES inspired key
transpose_key(); //transpose the original key
rotate_key(); //rotate the transposed key
if (junction == 0) {
check_m_length(); //adds padding if message length is not divisible by 16
encrypt(message); //encrypt
}
if (junction == 1) {
hex_to_char();
decrypt(message); //decrypt
}
clear_key(); //clears key arrays
}

void decryption() {
fopen_s(&text, "text.txt", "w+"); //creates text.txt, if it exists, its contents are cleared
printf("Type the encrypted message (max is 224 characters) :\n");
if (fgets_a(message, 226, stdin, 1) == 1) {
fclose(text); //closes text.txt
return;
}
printf("Type the symmetric key (16 numbers only) :");
if (fgets_a(key, 18, stdin, 2) == 1) {
fclose(text); //closes text.txt
return;
}
cipher(1); //sets the cipher function to add key
fclose(text); //closes text.txt
printf("\n");
return;
}

void encryption() {
fopen_s(&text, "text.txt", "w+"); //creates text.txt, if it exists, its contents are cleared
printf("Type your message (max 112 characters consisting of alphabets, numbers, '!?,.'
and whitespaces only) :\n");
if (fgets_a(message, 114, stdin, 0) == 1) {
fclose(text); //closes text.txt
return;
}
printf("Type the symmetric key (16 numbers only) :");
if (fgets_a(key, 18, stdin, 2) == 1) {
fclose(text); //closes text.txt
return;
}
cipher(0); //sets the cipher function to decrypt message
fclose(text); //closes text.txt
printf("\n");
return;
}

void reset() { //Resets the values to default


memset(message, 0, 202); //adds 0 from message[0] up to message[202]
memset(converted, 0, 202); //adds 0 form converted[0] up to converted[202]
memset(key, 0, 18); //adds 0 from key[0] up to key[18]
position_k = 0; //sets position_k to 0
dec = 0; //sets dec to 0
pos = 0; //sets pos to 0
}

int main(){
printf("1. Encryption\n2. Decryption\n\n0. Exit\n\n");
while (true) {
printf(">>>>");
if (fgets_a(selection, 3, stdin, 2) != 1) {
if (!(strcmp(selection, "1") == 0 || strcmp(selection, "2") == 0 ||
strcmp(selection, "0") == 0)) {
printf("Invalid input\n");
}
if (strcmp(selection, "1") == 0) {
encryption();
}
if (strcmp(selection, "2") == 0){
decryption();
}
if (strcmp(selection, "0") == 0) {
break;
}
}
reset(); //reset function that resets variable values
}
return 0;
}

4.2 Penetration testing tool


// brute_force.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>

FILE * proc1, * text, * programtext;


char path[102], message[202], decrypted[100], temp[2], c[2], numbers[]="0123456789" ,
out[16];
int check = 0;

void through(int fast) {


for (size_t j = 0; j < 10; j++) {
check = 0;
proc1 = _popen(path, "w");
out[fast] = numbers[j];
fprintf(proc1, "2\n%s\n%s\n0\n", message, out);
_pclose(proc1);
fopen_s(&programtext, "text.txt", "r");
fread(&decrypted, sizeof(char), 100, programtext);
fclose(programtext);
fprintf(text, "[%s]|%s\n", out, decrypted);
memset(decrypted, 0, 100);
}
}

int main()
{
printf("Type in encrypted message :");
fgets(message, 202, stdin);
printf("Type decryption program path :");
fgets(path, 102, stdin);
message[strcspn(message, "\n")] = 0;
fopen_s(&text, "bruteforce.txt", "a+");
through(0);
for (size_t i = 0; i < 10; i++) {
out[0] = numbers[i];
through(1);
}
for (size_t i = 0; i < 10; i++) {
out[0] = numbers[i];
for (size_t j = 0; j < 10; j++) {
out[1] = numbers[j];
through(2);
}
}
fclose(text);
return 0;
}

4.3 Normal Caesar Cipher Crack


// brute_force_caesar_shift.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>

int main()
{
FILE * text;
char message[102], ch;
int count = 1;
printf("Type encrypted message :");
fgets(message, 102, stdin);
message[strcspn(message, "\n")] = 0;
fopen_s(&text, "text.txt", "w+");
for (size_t i = 0; i < 26; i++) {
for (size_t j = 0; message[j] != '\0'; j++) {
ch = message[j];
if (ch >= 'a' && ch <= 'z') {
ch -= i;
if (ch < 'a') {
ch = ch + 'z' - 'a' + 1;
}
}
if (ch >= 'A' && ch <= 'Z') {
ch -= i;
if (ch < 'A') {
ch = ch + 'Z' - 'A' + 1;
}
}
if (ch >= '0' && ch <= '9') {
ch -= i;
while (ch < '0') {
ch = ch + '9' - '0' + 1;
}
}
fprintf(text, "%c", ch);
}
fprintf(text, "\n", ch);
}
return 0;
}

4.4 Unique Caesar Cipher Crack


// brute_force_caesar_shift.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>

int main()
{
FILE * text;
char message[102], ch;
int count = 1;
printf("Type encrypted message :");
fgets(message, 102, stdin);
message[strcspn(message, "\n")] = 0;
fopen_s(&text, "text.txt", "w+");
for (size_t i = 0; i < 26; i++) {
for (size_t j = 0; message[j] != '\0'; j++) {
ch = message[j];
if (ch >= 'a' && ch <= 'z') {
ch -= i;
if (ch < 'a') {
ch = ch + 'z' - 'a' + 1;
}
}
if (ch >= 'A' && ch <= 'Z') {
ch -= i;
if (ch < 'A') {
ch = ch + 'Z' - 'A' + 1;
}
}
if (ch >= '0' && ch <= '9') {
ch += i;
while (ch < '0') {
ch = ch + '9' - '0' - 1;
}
}
fprintf(text, "%c", ch);
}
fprintf(text, "\n", ch);
}
return 0;
}

Anda mungkin juga menyukai