Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added some cipher, linkedlist and stacks algotithms using c #421

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
92 changes: 92 additions & 0 deletions algorithms/ciphers/hill_cipher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
C code provided is an implementation of the RC4 algorithm, which is a widely used symmetric stream cipher. Here's what the code does:

Initialization: The code initializes the RC4 cipher with a secret key (key) and a plaintext message (plaintext) that you want to encrypt. It also creates arrays for storing the ciphertext and decrypted text.

Key Scheduling: The code performs key scheduling to initialize two arrays, S and T, of 256 bytes each. The key is used to create T, which is repeated to match the length of the key. The S array is initially filled with values from 0 to 255.

Key Mixing: The key and plaintext are mixed with the S array by performing a series of swaps. This process randomizes the S array based on the key and ensures that the key is well-distributed throughout the array.

Encryption: The code enters a loop to generate the keystream and use it to encrypt the plaintext. For each character in the plaintext, it generates a pseudo-random value (rnd) from the S array and XORs it with the corresponding character in the plaintext to produce the ciphertext.

Decryption: The code includes a rc4_decrypt function, which is essentially the same as the encryption process. This is because RC4 is a symmetric cipher, meaning that the same process is used for both encryption and decryption. To decrypt, you can simply call rc4_decrypt with the same key and the ciphertext.

Printing: Finally, the code prints the original message, the encrypted message (in hexadecimal format), and the decrypted message to the console.
*/


#include <stdio.h>
#include <stdlib.h>

#define MOD 26 // Modulus for the English alphabet

// Function to calculate the greatest common divisor (GCD) of two numbers
int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}

// Function to find the modular multiplicative inverse of a number
int modInverse(int a, int m) {
for (int x = 1; x < m; x++) {
if ((a * x) % m == 1) {
return x;
}
}
return -1; // Inverse doesn't exist
}

// Function to encrypt a message using a Hill cipher
void hillCipherEncrypt(char* message, int keyMatrix[3][3], int keySize) {
int i, j, k, msgLen;
int block[keySize];

// Calculate the message length
for (msgLen = 0; message[msgLen] != '\0'; msgLen++);

// Pad the message with 'X' to make it evenly divisible by the key size
while (msgLen % keySize != 0) {
message[msgLen] = 'X';
msgLen++;
}

// Perform encryption for each block of characters
for (i = 0; i < msgLen; i += keySize) {
// Convert the block to numerical values (A=0, B=1, ..., Z=25)
for (j = 0; j < keySize; j++) {
block[j] = message[i + j] - 'A';
}

// Encrypt the block using the key matrix
for (j = 0; j < keySize; j++) {
message[i + j] = 'A' + (char)((block[0] * keyMatrix[j][0] + block[1] * keyMatrix[j][1] + block[2] * keyMatrix[j][2]) % MOD);
}
}
}

int main() {
char message[] = "HELLOHILL"; // Message to be encrypted
int keyMatrix[3][3] = {{6, 24, 1}, {13, 16, 10}, {20, 17, 15}}; // Encryption key
int keySize = 3; // Size of the encryption key

// Check if the key matrix is valid (determinant should be co-prime with 26)
int det = keyMatrix[0][0] * (keyMatrix[1][1] * keyMatrix[2][2] - keyMatrix[2][1] * keyMatrix[1][2]) -
keyMatrix[0][1] * (keyMatrix[1][0] * keyMatrix[2][2] - keyMatrix[2][0] * keyMatrix[1][2]) +
keyMatrix[0][2] * (keyMatrix[1][0] * keyMatrix[2][1] - keyMatrix[2][0] * keyMatrix[1][1]);
det = (det % MOD + MOD) % MOD; // Ensure the determinant is positive

if (gcd(det, MOD) != 1) {
printf("The key matrix is not valid for Hill cipher encryption.\n");
return 1;
}

// Encrypt the message
hillCipherEncrypt(message, keyMatrix, keySize);

// Print the encrypted message
printf("Encrypted message: %s\n", message);

return 0;
}
79 changes: 79 additions & 0 deletions algorithms/ciphers/rivest_cipher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
C code provided is an implementation of the RC4 algorithm, which is a widely used symmetric stream cipher. Here's what the code does:

Initialization: The code initializes the RC4 cipher with a secret key (key) and a plaintext message (plaintext) that you want to encrypt. It also creates arrays for storing the ciphertext and decrypted text.

Key Scheduling: The code performs key scheduling to initialize two arrays, S and T, of 256 bytes each. The key is used to create T, which is repeated to match the length of the key. The S array is initially filled with values from 0 to 255.

Key Mixing: The key and plaintext are mixed with the S array by performing a series of swaps. This process randomizes the S array based on the key and ensures that the key is well-distributed throughout the array.

Encryption: The code enters a loop to generate the keystream and use it to encrypt the plaintext. For each character in the plaintext, it generates a pseudo-random value (rnd) from the S array and XORs it with the corresponding character in the plaintext to produce the ciphertext.

Decryption: The code includes a rc4_decrypt function, which is essentially the same as the encryption process. This is because RC4 is a symmetric cipher, meaning that the same process is used for both encryption and decryption. To decrypt, you can simply call rc4_decrypt with the same key and the ciphertext.

Printing: Finally, the code prints the original message, the encrypted message (in hexadecimal format), and the decrypted message to the console.
*/


#include <stdio.h>
#include <string.h>

void rc4_encrypt(unsigned char *key, unsigned char *plaintext, unsigned char *ciphertext) {
unsigned char S[256];
unsigned char T[256];
int keylen = strlen((char *)key);
int plaintextlen = strlen((char *)plaintext);
int i, j = 0, k = 0;

for (i = 0; i < 256; i++) {
S[i] = i;
T[i] = key[i % keylen];
}

for (i = 0; i < 256; i++) {
j = (j + S[i] + T[i]) % 256;
// Swap S[i] and S[j]
unsigned char temp = S[i];
S[i] = S[j];
S[j] = temp;
}

i = 0;
j = 0;

for (int m = 0; m < plaintextlen; m++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
// Swap S[i] and S[j]
unsigned char temp = S[i];
S[i] = S[j];
S[j] = temp;

int rnd = S[(S[i] + S[j]) % 256];
ciphertext[m] = plaintext[m] ^ rnd;
}
}

void rc4_decrypt(unsigned char *key, unsigned char *ciphertext, unsigned char *plaintext) {
rc4_encrypt(key, ciphertext, plaintext); // RC4 decryption is the same as encryption
}

int main() {
unsigned char key[] = "SecretKey";
unsigned char plaintext[] = "Hello, RC4!";
unsigned char ciphertext[12];
unsigned char decryptedtext[12];

rc4_encrypt(key, plaintext, ciphertext);
rc4_decrypt(key, ciphertext, decryptedtext);

printf("Original message: %s\n", plaintext);
printf("Encrypted message: ");
for (int i = 0; i < 12; i++) {
printf("%02X ", ciphertext[i]);
}
printf("\n");
printf("Decrypted message: %s\n", decryptedtext);

return 0;
}
108 changes: 108 additions & 0 deletions algorithms/converting/infix_to_postfix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_SIZE 100

// Define a structure for a stack
struct Stack {
char data[MAX_SIZE];
int top;
};

// Function to initialize a stack
void initialize(struct Stack* stack) {
stack->top = -1;
}

// Function to check if the stack is empty
int isEmpty(struct Stack* stack) {
return (stack->top == -1);
}

// Function to push an element onto the stack
void push(struct Stack* stack, char item) {
if (stack->top >= MAX_SIZE - 1) {
printf("Stack overflow\n");
exit(1);
}
stack->data[++stack->top] = item;
}

// Function to pop an element from the stack
char pop(struct Stack* stack) {
if (isEmpty(stack)) {
printf("Stack underflow\n");
exit(1);
}
return stack->data[stack->top--];
}

// Function to get the precedence of an operator
int getPrecedence(char operator) {
if (operator == '+' || operator == '-') {
return 1;
} else if (operator == '*' || operator == '/') {
return 2;
}
return 0;
}

// Function to check if a character is an operator
int isOperator(char character) {
return (character == '+' || character == '-' || character == '*' || character == '/');
}

// Function to convert infix to postfix expression
void infixToPostfix(char infix[], char postfix[]) {
struct Stack operatorStack;
initialize(&operatorStack);

int length = strlen(infix);
int j = 0;

for (int i = 0; i < length; i++) {
char symbol = infix[i];

if (isalnum(symbol)) {
postfix[j++] = symbol;
} else if (symbol == '(') {
push(&operatorStack, symbol);
} else if (symbol == ')') {
while (!isEmpty(&operatorStack) && operatorStack.data[operatorStack.top] != '(') {
postfix[j++] = pop(&operatorStack);
}
// Pop the corresponding '('
if (!isEmpty(&operatorStack) && operatorStack.data[operatorStack.top] == '(') {
pop(&operatorStack);
}
} else if (isOperator(symbol)) {
while (!isEmpty(&operatorStack) && getPrecedence(operatorStack.data[operatorStack.top]) >= getPrecedence(symbol)) {
postfix[j++] = pop(&operatorStack);
}
push(&operatorStack, symbol);
}
}

// Pop any remaining operators from the stack
while (!isEmpty(&operatorStack)) {
postfix[j++] = pop(&operatorStack);
}

// Null-terminate the postfix expression
postfix[j] = '\0';
}

int main() {
char infix[MAX_SIZE], postfix[MAX_SIZE];

printf("Enter an infix expression: ");
scanf("%s", infix);

infixToPostfix(infix, postfix);

printf("The postfix expression is: %s\n", postfix);

return 0;
}
90 changes: 90 additions & 0 deletions algorithms/converting/postfix_to_infix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_SIZE 100

// Define a structure for a stack
struct Stack {
char data[MAX_SIZE][MAX_SIZE]; // Use a 2D array to store operands and operators
int top;
};

// Function to initialize a stack
void initialize(struct Stack* stack) {
stack->top = -1;
}

// Function to check if the stack is empty
int isEmpty(struct Stack* stack) {
return (stack->top == -1);
}

// Function to push an element onto the stack
void push(struct Stack* stack, char item[], int isOperator) {
if (stack->top >= MAX_SIZE - 1) {
printf("Stack overflow\n");
exit(1);
}

if (isOperator) {
// Enclose operators in parentheses for proper infix expression
sprintf(stack->data[++stack->top], "(%s)", item);
} else {
strcpy(stack->data[++stack->top], item);
}
}

// Function to pop an element from the stack
void pop(struct Stack* stack, char result[]) {
if (isEmpty(stack)) {
printf("Stack underflow\n");
exit(1);
}
strcpy(result, stack->data[stack->top--]);
}

// Function to convert postfix to infix expression
void postfixToInfix(char postfix[], char infix[]) {
struct Stack operandStack;
initialize(&operandStack);

int length = strlen(postfix);

for (int i = 0; i < length; i++) {
char symbol = postfix[i];

if (isalnum(symbol)) {
char operand[2];
operand[0] = symbol;
operand[1] = '\0';
push(&operandStack, operand, 0); // 0 indicates it's an operand
} else if (symbol == '+' || symbol == '-' || symbol == '*' || symbol == '/') {
char operand1[MAX_SIZE], operand2[MAX_SIZE];
pop(&operandStack, operand1);
pop(&operandStack, operand2);

char expression[MAX_SIZE];
sprintf(expression, "%s %c %s", operand2, symbol, operand1);

push(&operandStack, expression, 1); // 1 indicates it's an operator
}
}

// The final result is at the top of the stack
pop(&operandStack, infix);
}

int main() {
char postfix[MAX_SIZE], infix[MAX_SIZE];

printf("Enter a postfix expression: ");
scanf("%s", postfix);

postfixToInfix(postfix, infix);

printf("The infix expression is: %s\n", infix);

return 0;
}
Loading