- El cifrado César sustituye cada letra por otra desplazada un número fijo de posiciones, definido por una clave.
- En C se implementa convirtiendo letras a códigos numéricos, aplicando sumas y módulo 26 y respetando mayúsculas y minúsculas.
- Funciones como isalpha, isupper, islower, strlen y un diseño modular facilitan un programa interactivo para cifrar, descifrar y aplicar fuerza bruta.
- Es un algoritmo históricamente relevante pero criptográficamente débil, ideal como ejercicio educativo y de aprendizaje de programación.
Si te estás iniciando en C y quieres un proyecto práctico, crear un programa de cifrado y descifrado en código César es una opción perfecta. Es sencillo, te obliga a manipular cadenas, a trabajar con caracteres y a pensar en términos matemáticos, pero sin volverte loco con la complejidad.
Además de servir como ejercicio de programación, el cifrado César es una puerta de entrada estupenda al mundo de la criptografía: entenderás qué es una clave, por qué algunos sistemas son débiles y cómo se puede atacar un cifrado por fuerza bruta. Vamos a verlo paso a paso, con teoría, ejemplos y varios enfoques de implementación en C.
Qué es el cifrado César y de dónde sale
El llamado cifrado César, o cifrado por desplazamiento, es uno de los sistemas criptográficos más antiguos que existen. Su nombre viene de Julio César, que se dice que lo utilizaba para mandar mensajes militares camuflados a sus generales, de forma que si alguien interceptaba el texto no pudiera entenderlo a simple vista.
La idea es muy simple: cada letra del mensaje original se sustituye por otra que está un número fijo de posiciones más adelante o más atrás en el alfabeto. Ese número de posiciones es la clave. Por ejemplo, con clave 3, A pasa a D, B a E, C a F y así sucesivamente hasta llegar a Z, donde el alfabeto “da la vuelta” y se vuelve a empezar por A.
Este esquema pertenece a los cifrados por sustitución monoalfabética: siempre que aparece la misma letra en el texto plano, se transforma en la misma letra cifrada. Eso hace que sea muy fácil de comprender e implementar, pero también muy sencillo de romper con un poco de análisis.

Fundamentos matemáticos del cifrado César
Detrás de este método tan clásico hay una formulación matemática muy compacta. Numeramos cada letra de 0 a n-1 (donde n es el tamaño del alfabeto), podemos expresar el cifrado como:
C = (P + k) mod n
Donde P es la posición de la letra original, C es la posición de la letra cifrada, k es la clave de desplazamiento y n es el número total de símbolos del alfabeto (26 en el alfabeto inglés sin ñ). El operador mod se encarga de que, al llegar al final del alfabeto, el conteo vuelva a empezar desde el principio.
Para recuperar el mensaje basta con invertir la operación:
P = (C − k) mod n
En la práctica, cuando lo implementamos en C no trabajamos con posiciones abstractas, sino con códigos numéricos de caracteres (ASCII o UTF-8 compatible). Las mayúsculas de la A a la Z ocupan los valores 65 a 90, y las minúsculas de la a a la z van de 97 a 122. Aprovechando esos rangos podemos restar el código base (‘A’ o ‘a’), aplicar el desplazamiento con módulo 26 y volver a sumar la base.
Un detalle clave: la operación en módulo garantiza el “efecto circular” del alfabeto. Si desplazas Z tres posiciones con clave 3 en el rango de mayúsculas, acabas en C, porque el cálculo se hace dentro del intervalo 0-25 y luego se convierte de nuevo en código ASCII.
Conceptos básicos de criptografía que necesitas
Trabajar con el cifrado César te permite interiorizar varios conceptos clásicos de criptografía sin entrar todavía en matemáticas avanzadas ni en algoritmos modernos.
Al mensaje original sin cifrar lo llamamos texto plano. Es lo que quieres comunicar: por ejemplo, «Adios» o una frase completa. El resultado después de aplicar el cifrado es el texto cifrado o criptograma, que parece una ristra de letras sin sentido, como «Dglrv».
El proceso de convertir texto plano en texto cifrado se denomina cifrado o encriptación, mientras que la operación inversa se llama descifrado o desencriptación. En ambos casos se utiliza una clave, que en el cifrado César es simplemente un entero entre 1 y 26 (o entre 0 y 25, según cómo lo definas en el programa), y su aplicación en servicios como Gmail.
Un punto interesante es que, aunque para un usuario sin conocimientos el resultado parezca seguro, la seguridad real del cifrado César es prácticamente nula. Solo hay 25 claves posibles en el alfabeto latino estándar, así que un atacante puede probarlas todas en cuestión de milisegundos con un programa de fuerza bruta.

ASCII, ordinales y conversión entre letras y números
Para implementar este sistema en C hay que entender bien cómo representan los ordenadores los caracteres. Históricamente se utilizaba principalmente ASCII, que asigna a cada símbolo un número entero entre 0 y 127, aunque en la práctica se usan sobre todo los rangos imprimibles de 32 a 126.
Como ya hemos comentado, las letras mayúsculas A-Z tienen códigos del 65 al 90, y las minúsculas a-z del 97 al 122. Los dígitos 0-9 van del 48 al 57. Hoy en día lo habitual es trabajar con UTF-8, pero para los caracteres básicos mantiene los mismos valores que ASCII, de modo que nuestro código seguirá siendo válido.
El truco habitual consiste en convertir una letra a su código numérico, manipular ese número con sumas, restas y módulos, y volver a convertirlo a carácter. En Python esto se hace con las funciones ord() y chr(); en C no existen como tales, pero el propio tipo char se puede tratar como entero, y las constantes de carácter como ‘A’ o ‘a’ actúan como valores numéricos.
Por ejemplo, para desplazar la letra ‘A’ tres posiciones hacia adelante en C puedes pensar así: ‘A’ tiene código 65, le sumas 3 y obtienes 68, que corresponde a ‘D’. Cuando trabajes con mayúsculas restas primero ‘A’ para normalizar el rango a 0-25, aplicas el desplazamiento en módulo 26 y luego vuelves a sumar ‘A’ para recuperar el código correcto.
Diseño general de un programa en C para cifrado César
Un programa en C que implemente el cifrado y descifrado César suele seguir siempre una estructura muy parecida, aunque cambien los detalles según el estilo del autor:
- Solicitud del texto al usuario: se pide una cadena que será el mensaje a cifrar o descifrar.
- Lectura de la clave numérica: el usuario introduce el desplazamiento, normalmente un entero entre 1 y 26.
- Elección del modo: encriptar, desencriptar o incluso fuerza bruta si quieres añadir ese extra.
- Función principal de traducción: recibe el mensaje, la clave y el modo, recorre la cadena y genera el resultado procesado.
- Salida por pantalla: se imprime el criptograma o el texto plano recuperado.
El corazón del algoritmo es siempre el mismo: recorrer la cadena carácter a carácter, comprobar si cada símbolo es una letra y, en caso afirmativo, aplicarle la transformación adecuada respetando mayúsculas y minúsculas. Todo lo que no sea letra (espacios, signos de puntuación, números, etc.) se suele dejar tal cual.

Uso de funciones estándar de C para trabajar con caracteres
Para que el código quede más limpio y robusto es muy recomendable apoyarse en la cabecera <ctype.h>, que ofrece varias funciones utilísimas para clasificar caracteres.
Funciones clave:
En concreto, para el cifrado César te interesan especialmente:
- isalpha(c): devuelve un valor distinto de cero si c es una letra (mayúscula o minúscula), y cero en caso contrario.
- isupper(c): comprueba si c es una letra mayúscula.
- islower(c): comprueba si c es una letra minúscula.
Con estas funciones puedes filtrar fácilmente qué caracteres se van a procesar. Si isalpha(c) es falso, simplemente copias el símbolo al resultado y pasas al siguiente. Si es una letra, decides el rango adecuado (A-Z o a-z) según isupper o islower y aplicas el desplazamiento sin miedo a salirte del alfabeto correspondiente.
En paralelo, vas a necesitar la cabecera <string.h> para funciones como strlen(), que te permite conocer la longitud de la cadena y usarla en un bucle for o while al iterar sobre el mensaje.
Ejemplo de implementación básica de cifrado César en C
Una versión muy habitual del programa en C define una función, que podríamos llamar por ejemplo cesar(), encargada de transformar in-place la cadena recibida o de generar una copia cifrada a partir de un buffer de entrada.
Flujo típico:
- En main(), se pide al usuario el texto a procesar.
- Se pregunta la clave de desplazamiento y se valida que esté en el rango permitido.
- Se llama a la función de cifrado pasando el texto y la clave.
- Se muestra por pantalla el resultado.
Estructura interna:
- Calcular la longitud del texto con strlen() para fijar los límites del bucle.
- Recorrer la cadena carácter a carácter usando un índice entero.
- Comprobar si cada carácter es letra mayúscula, minúscula o no es alfabético.
- Aplicar el desplazamiento con la fórmula adecuada y el operador % 26.
- Dejar sin cambios los caracteres no alfabéticos.
El uso del operador % 26 es esencial para que el resultado se mantenga dentro del alfabeto. De este modo, si desplazas la z con clave 3, obtienes c en lugar de un símbolo extraño del código ASCII.
Manejo de cadenas en C: scanf, fgets y búferes
Uno de los puntos más delicados al escribir estos programas en C no es el cifrado en sí, sino la forma de leer la cadena desde la entrada estándar. Aunque scanf con » %s» parece tentador, tiene varios problemas: corta la lectura en el primer espacio, no controla bien el tamaño del búfer y es fácil provocar desbordamientos si no se es cuidadoso.
Por eso, muchos ejemplos modernos optan por usar fgets() para leer líneas completas. Esta función recibe el búfer, su tamaño máximo y la fuente de entrada (normalmente stdin) y se encarga de no sobrepasar los límites. La contrapartida es que suele dejar el salto de línea al final de la cadena, así que suele ser buena idea limpiarlo manualmente recorriendo la cadena y sustituyendo el ‘\n’ por ‘\0’ cuando aparezca.
En cualquier caso, el algoritmo de cifrado es independiente de cómo hayas obtenido la cadena: puedes encapsular la lógica de César en una función que reciba un char[] ya preparado, y luego decidir en main si rellenas ese array con fgets, scanf o cualquier otro método según tus necesidades.

Estructura de un programa interactivo completo
Más allá de la función básica de cifrado, se puede construir un programa interactivo bastante completo que permita al usuario elegir si quiere encriptar, desencriptar o incluso probar todas las claves posibles (modo fuerza bruta).
Una organización muy clara consiste en separar la lógica en varias funciones:
- obtenerModo(): pregunta al usuario si desea cifrar, descifrar o usar fuerza bruta y devuelve un carácter o cadena corta que represente el modo elegido.
- obtenerMensaje(): se encarga de pedir el texto a procesar y devolverlo.
- obtenerClave(): solicita una clave al usuario, obliga a introducir un valor entre 1 y un máximo (por ejemplo 26) y devuelve ese entero.
- obtenerMensajeTraducido(modo, mensaje, clave): aplica la lógica de cifrado o descifrado según el modo, devolviendo el texto transformado.
En modo descifrado resulta muy cómodo trabajar con la misma función que para cifrar, pero cambiando el signo de la clave. Es decir, si el usuario elige desencriptar, se multiplica la clave por -1 y se aplica el mismo algoritmo que usaríamos para cifrar. De esa forma evitas duplicar código.
El modo de fuerza bruta añade una curiosidad nada desdeñable: automatiza el proceso de probar todas las claves posibles. El programa recorre en un bucle desde 1 hasta el tamaño máximo de clave, llama en cada iteración a la función de traducción en modo descifrado y muestra cada resultado junto con la clave utilizada. Basta con que el usuario observe cuál de las líneas tiene sentido en español para deducir qué desplazamiento se empleó originalmente.
#include <stdio.h> // Para printf y scanf
#include <string.h> // Para strlen
// Función que aplica el cifrado César
void caesar_cipher(char *text, int shift) {
for (int i = 0; i < strlen(text); i++) {
char c = text[i]; // carácter actual
// Si es letra mayúscula
if (c >= 'A' && c <= 'Z') {
text[i] = ((c - 'A' + shift) % 26) + 'A';
}
// Si es letra minúscula
else if (c >= 'a' && c <= 'z') {
text[i] = ((c - 'a' + shift) % 26) + 'a';
}
// Si no es letra, lo dejamos igual
}
}
int main() {
char mensaje[100]; // buffer para el texto
int desplazamiento; // valor del shift
printf("Introduce el mensaje a cifrar: ");
scanf("%99[^\n]", mensaje); // lee hasta 99 caracteres incluyendo espacios
printf("Introduce el desplazamiento (ej. 3): ");
scanf("%d", &desplazamiento);
// Aplicamos el cifrado
caesar_cipher(mensaje, desplazamiento);
printf("Mensaje cifrado: %s\n", mensaje);
return 0;
}
Tratamiento de mayúsculas, minúsculas y caracteres especiales
Algo que a menudo se pasa por alto al principio es la importancia de respetar la forma de las letras y no destrozar el texto. Un buen programa de cifrado César debe tratar por separado mayúsculas y minúsculas, y dejar intactos los símbolos que no pertenezcan al alfabeto.
La lógica típica es:
- Si el símbolo no pasa la comprobación isalpha(), se copia directamente al resultado sin ningún cambio.
- Si es una letra mayúscula, se normaliza el valor restando ‘A’, se aplica el desplazamiento en módulo 26 y luego se suma ‘A’ de nuevo.
- Si es una letra minúscula, se hace lo mismo pero con el rango basado en ‘a’.
- Si al sumar la clave te sales por arriba del rango (más allá de ‘Z’ o ‘z’), restas 26; si te sales por abajo al restar, sumas 26.
De esta manera consigues que textos como «Adios» con clave 3 se conviertan en «Dglrv» respetando la capital inicial y el resto en minúsculas, y que al descifrar vuelvas exactamente al original.
Es importante también ser consciente de que el cifrado César no altera espacios ni signos de puntuación, lo que permite mantener la estructura visual de frases y párrafos pero hace que la longitud del mensaje y la posición relativa de palabras siga siendo visible para un atacante.
Redactor apasionado del mundo de los bytes y la tecnología en general. Me encanta compartir mis conocimientos a través de la escritura, y eso es lo que haré en este blog, mostrarte todo lo más interesante sobre gadgets, software, hardware, tendencias tecnológicas, y más. Mi objetivo es ayudarte a navegar por el mundo digital de forma sencilla y entretenida.