Compilar y ejecutar
Guarda el programa como CaesarCipher.java, porque el nombre del archivo debe coincidir con el de la clase. Después ejecuta estos dos comandos en la misma carpeta:
javac CaesarCipher.javajava CaesarCipherEl primero compila el código y el segundo lo ejecuta e imprime el texto cifrado. Si el cifrado en sí es nuevo para ti, la guía lo explica sin código.
Cómo funciona el código
En Java un char también es un número, así que puedes operar con él directamente: 'H' - 'A' da 7, la posición de la letra en el alfabeto. Tras sumar el desplazamiento, Math.floorMod mantiene el resultado entre 0 y 25, de modo que con un desplazamiento de 3 la Z cae en la C.
base + index devuelve un int, y por eso aparece la conversión (char). El resultado se acumula en un StringBuilder, ya que añadir a un String dentro de un bucle crea un objeto nuevo cada vez.
Espacios, signos y cifras pasan por la rama else sin cambios. La comprobación c < 128 hace falta porque Character.isLetter también acepta la ñ y las vocales con tilde: sin ella se convertirían en otra letra cualquiera y el texto ya no se podría descifrar bien.
Descifrar en Java
No hace falta un segundo método. Descifrar es desplazar en sentido contrario, así que basta con pasar un número negativo:
System.out.println(caesar("¡Krod, pxqgr!", -3));// ¡Hola, mundo!Para esto sirve Math.floorMod. El % de Java conserva el signo del número de la izquierda: -3 % 26 da -3, que ni siquiera es una letra. Math.floorMod(-3, 26) da 23, y la A vuelve a la X. En la versión en Python, el propio % ya se comporta así.
Leer datos con Scanner
Muchos ejercicios piden un programa que lea el texto y el desplazamiento por teclado. Coloca el import al principio del archivo y sustituye main por esto:
import java.util.Scanner; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Texto: "); String text = scanner.nextLine(); System.out.print("Desplazamiento: "); int shift = scanner.nextInt(); System.out.println(caesar(text, shift));}Lee primero el texto. nextInt() deja pendiente el salto de línea, y un nextLine() posterior devolvería una cadena vacía.
Romper el cifrado por fuerza bruta
Con 26 letras solo hay 25 desplazamientos posibles, y un bucle corto basta para leer el mensaje sin la clave. Busca en la salida la línea que tenga sentido:
public static void crack(String text) { for (int shift = 1; shift < 26; shift++) { System.out.println(shift + " " + caesar(text, -shift)); }} public static void main(String[] args) { crack("¡Krod, pxqgr!"); // 1 ¡Jqnc, owpfq! // 2 ¡Ipmb, nvoep! // 3 ¡Hola, mundo! // ...}El artículo sobre el ataque de fuerza bruta entra en más detalle, y el descifrador en línea hace lo mismo en tu navegador.
Cifrado César con la ñ
Para desplazar también la ñ, guarda el alfabeto en un String y busca cada carácter con indexOf(). Son las mismas 27 letras que usa nuestra herramienta:
static final String ALPHABET = "abcdefghijklmnñopqrstuvwxyz"; public static String caesarAlphabet(String text, int shift) { StringBuilder result = new StringBuilder(); for (char c : text.toCharArray()) { int position = ALPHABET.indexOf(Character.toLowerCase(c)); if (position == -1) { result.append(c); } else { int index = Math.floorMod(position + shift, ALPHABET.length()); char next = ALPHABET.charAt(index); result.append(Character.isUpperCase(c) ? Character.toUpperCase(next) : next); } } return result.toString();} public static void main(String[] args) { System.out.println(caesarAlphabet("El niño", 3)); // Hñ plqr}Ahora la vuelta depende de ALPHABET.length(), así que no tienes que escribir el 27 en ningún sitio. Puedes comparar el resultado en la herramienta de cifrado César con el alfabeto español.
Cifrar un archivo de texto
Files.readString y Files.writeString leen y escriben un archivo entero en una línea, en UTF-8 por defecto, de manera que la ñ y las tildes se conservan. Pueden fallar, por lo que main debe declarar throws IOException.
import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path; public static void main(String[] args) throws IOException { String text = Files.readString(Path.of("message.txt")); Files.writeString(Path.of("encrypted.txt"), caesar(text, 3));}Probar el código
Pon estas líneas en main para detectar los errores habituales. Java ignora assert si no lo activas, así que ejecuta el programa con java -ea CaesarCipher. Si todo va bien, imprime OK.
assert caesar("ABC", 3).equals("DEF");assert caesar("xyz", 3).equals("abc");assert caesar("Hello, World!", 5).equals("Mjqqt, Btwqi!");assert caesar(caesar("Java", 7), -7).equals("Java");assert caesar("A", 26).equals("A");assert caesar("é", 3).equals("é");System.out.println("OK");Errores frecuentes
El más común es usar % con un desplazamiento negativo, como vimos antes. Otro es olvidar la conversión: result.append(base + index) añade el número 75 cuando querías la letra K. Y compara las cadenas de tus pruebas con equals(), porque == solo mira si son el mismo objeto.
Preguntas frecuentes
¿Qué versión de Java necesito?
El programa principal funciona en Java 8 y posteriores. El ejemplo de archivos necesita Java 11, que añadió Files.readString. Hemos compilado y ejecutado el código de esta página con Java 21.
¿Sirve para proteger datos reales?
No. El bucle de arriba lo rompe en segundos. Úsalo para aprender y para pasatiempos. Para datos reales, Java incluye cifrado moderno como AES en el paquete javax.crypto.
¿Cómo compruebo que mi resultado es correcto?
Introduce el mismo texto y desplazamiento en nuestra herramienta de cifrado César y compara. También puedes llamar a la API REST gratuita desde tus pruebas.