Este codigo no se puede usar en producción ya que es necesario remover tanto la clave hardcodeada y
eliminar cualquier printf que muestre secretos
Definiciones iniciales
~ `WIN32_LEAN_AND_MEAN` reduce macros innecesarias del `windows.h`
~ `bcrypt.h` se usa para `BCryptGenRandom` (RNG de Windows)
~ `crypto/aes.h` es la API de tiny-aes que se usa (proporciona `AES_ctx`, `AES_init_ctx_iv`,
`AES_CBC_encrypt_buffer`)
checkPadding
┌─[ c ]─────────────────────────────────────────────────────────────────────────────────────────────
bool checkPadding(unsigned char payload[], size_t sizePayload) {
return (sizePayload % 16 == 0)
? true
: false;
}
└───────────────────────────────────────────────────────────────────────────────────────────────────~ Devuelve `true` si `sizePayload` ya es múltiplo de 16 (tamaño de bloque AES), `false` si no
~ AES-CBC en tiny-aes requiere que el buffer a cifrar tenga longitud múltiplo de 16 bytes
fillPadding
┌─[ c ]─────────────────────────────────────────────────────────────────────────────────────────────
void fillPadding(unsigned char payload[], size_t sizePayload, unsigned char **newPayload, size_t *newSize) {
size_t size = ((sizePayload + (15)) / 16) * 16;
unsigned char *pNewpayload = (unsigned char *) malloc(size);
if (!pNewpayload) {
*newPayload = NULL;
*newSize = 0;
return;
}
memcpy(pNewpayload, payload, sizePayload);
memset(pNewpayload + sizePayload, 0x00, size - sizePayload);
*newSize = size;
*newPayload = pNewpayload;
}
└───────────────────────────────────────────────────────────────────────────────────────────────────~ Calcula el siguiente múltiplo de 16 para `sizePayload`
~ Reserva `size` bytes con `malloc`
~ Copia `sizePayload` bytes desde `payload` a la nueva área
~ Rellena el resto con ceros (`0x00`)
~ Devuelve el puntero en `*newPayload` y tamaño en `*newSize`
encriptar
┌─[ c ]─────────────────────────────────────────────────────────────────────────────────────────────
bool encriptar(unsigned char payload[], size_t sizePayload, unsigned char **encryptedPayload,
size_t *encryptedPayloadSize, bool *must_free) {
if (!encryptedPayload || !encryptedPayloadSize) return false;
unsigned char *newPayload = NULL;
size_t newPayloadSize;
if (!checkPadding(payload, sizePayload)) {
fillPadding(payload, sizePayload, &newPayload, &newPayloadSize);
if (!newPayload) return false;
*must_free = true;
} else {
newPayload = payload;
newPayloadSize = sizePayload;
*must_free = false;
}
uint8_t iv[16] = {0};
NTSTATUS st = BCryptGenRandom(NULL, iv, sizeof iv, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (st != 0) {
puts("Error al generar el IV");
}
printf("IV usado:\n");
for (int i = 0; i < 16; i++) {
printf("0x%02X ", iv[i]);
}
uint8_t key[16] = "extraterrestrial";
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_encrypt_buffer(&ctx, newPayload, (uint32_t) newPayloadSize);
*encryptedPayload = newPayload;
*encryptedPayloadSize = newPayloadSize;
return true;
}
└───────────────────────────────────────────────────────────────────────────────────────────────────~ Comprueba `encryptedPayload` y `encryptedPayloadSize` no nulos. Bien evitar writes a punteros
nulos
~ No comprueba `must_free` (se asume que es válido si se pasa)
A continuación proporciono el enlace al código completo en mi github
Recurso externo: abrir recurso