Files
AES-in-C/main.c
2025-03-22 14:25:23 +01:00

153 lines
3.8 KiB
C

/**
* Advanced Encryption Standard (AES) implementation v1.0
* ------------------------------------------------------------
*
* This program encrypts a given 128-bit block of data with a
* 128-bit key using AES cipher. To do so, AES operates in 10
* rounds and generates 11 round keys. The AES-128 algorithm
* steps can be summarized as follow:
*
* 1. KeyExpansion
* 2. AddRoundKey
*
* 3. Nine rounds:
* SubBytes
* ShiftRows
* MixColumns
* AddRoundKey
*
* 4. Last round:
* SubBytes
* ShiftRows
* AddRoundKey
*
* Reference:
* https://doi.org/10.6028/NIST.FIPS.197-upd1
*
* This AES implementation has been written by
* Sacha Meurice (https://github.com/sameuric).
*
* 2025, Licence: MIT.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "AES/aes.h"
// Convert a string to its corresponding uint8 array.
static void char2uint(const char*, uint8_t*);
// Convert a uint8 array to its corresponding string.
static void uint2char(const uint8_t*, char*, size_t);
// Check if input is made up of hexadecimal chars only.
static int isHeXString(const char*);
int main(int argc, char** argv) {
if (argc != 3) {
fprintf(stderr, "ERROR: Invalid number of arguments.\n");
fprintf(stderr, "Usage: %s <aes_input> <aes_key>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (strlen(argv[1]) != AES_PARAM_SIZE) {
fprintf(stderr, "ERROR: Invalid format for argument '%s'. Expected 128-bit input.\n", argv[1]);
exit(EXIT_FAILURE);
}
if (strlen(argv[2]) != AES_PARAM_SIZE) {
fprintf(stderr, "ERROR: Invalid format for argument '%s'. Expected 128-bit key.\n", argv[2]);
exit(EXIT_FAILURE);
}
/* Check if parameters are hexadecimal strings. */
if (!isHeXString(argv[1])) {
fprintf(stderr, "ERROR: Argument '%s' is not a hexadecimal string.\n", argv[1]);
exit(EXIT_FAILURE);
}
if (!isHeXString(argv[2])) {
fprintf(stderr, "ERROR: Argument '%s' is not a hexadecimal string.\n", argv[2]);
exit(EXIT_FAILURE);
}
// Store AES input and key as uint8 arrays.
uint8_t input[AES_BLOCK_SIZE], key[AES_BLOCK_SIZE];
char2uint(argv[1], input);
char2uint(argv[2], key);
// AES encryption.
AES_init();
AES_encrypt(input, key);
// Output includes the final NULL char.
char output[AES_PARAM_SIZE + 1] = {0};
uint2char(input, output, AES_BLOCK_SIZE);
printf("CIPHERTEXT: %s\n", output);
return EXIT_SUCCESS;
}
// Check if input is made up of hexadecimal chars only.
static int isHeXString(const char* s) {
if (s == NULL)
return 0;
while (*s != '\0') {
const char c = *s;
int hexChar = (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F');
if (!hexChar)
return 0;
++s;
}
return 1; // Correct format.
}
// Convert plaintext to bytes array
static void char2uint(const char* s, uint8_t* b) {
const size_t len = strlen(s)/2;
char hex_byte[3] = {0};
for (size_t i = 0; i < len; ++i) {
memcpy(hex_byte, s + 2*i, 2);
b[i] = (uint8_t)strtol(hex_byte, NULL, 16);
}
}
// Convert bytes array to plaintext
static void uint2char(const uint8_t* b, char* s, size_t len) {
const char* hexa = "0123456789abcdef";
for (size_t i = 0; i < len; ++i) {
s[2*i] = hexa[b[i] >> 4]; // High nibble
s[2*i + 1] = hexa[b[i] & 0x0F]; // Low nibble
}
}