Cifrado César escrito en Java

El cifrado césar consiste en intercambiar las letras de un mensaje un número de posiciones determinadas por una clave. Más información de su historia y funcionamiento haciendo clic aquí.

El código que muestro más abajo es una versión del cifrado César tradicional pero empleando el alfabeto ASCII. Este alfabeto tiene 255 caracteres por lo que las posibilidades de cifrado y la dificultad para desencriptar se ven aumentadas. Sin embargo, las fórmulas que emplearemos son las mismas que se emplearon hace más de 2000 años, con una ligera variación:

*Se usa 27, porque en el alfabeto tradicional tenemos 27 caracteres.

Código ASCII

El código tiene dos versiones, una sin optimizar en la que se desglosa el proceso línea por línea y otra optimizada pero algo menos legible.

Ambos scripts están pensados para ser ejecutados desde una terminal de un sistema operativo en el que se encuentre instalado el JDK 7 u 8 (clic aquí para instalarlo en Linux).

Si tienes algún problema con la entrada de texto en Java haz clic aquí.

Si encuentras bugs, se te ocurren ideas para mejorar el código o lo que sea, te invito a expresarte en los comentarios.

Versión primera

/**
 * Created by erwol on 03/03/2016 at 12:39
 * For further information visit http://www.archecode.org
 */
import java.util.Scanner;
import java.io.Console;
public class Cesar {
    private static Scanner lee = new Scanner(System.in);
    public static void main(String args[]){
        int op = -1;
        String texto = null;
        Console consola = System.console();
        int clave = 0;
        while(op != 0){
            System.out.print("ntCIFRADO CÉSARn0.- Salirn1.- Cifrarn2.- Descifrarn> ");
            op = lee.nextInt();
            switch(op){
                case 0:break;
                case 1:
                    System.out.printf("1. Introduzca el texto a cifrarn> ");
                    texto = consola.readLine();
                    System.out.printf("2. Introduzca la clave con la que se codificará el texton>");
                    clave = lee.nextInt();
                    System.out.println("3. Cadena cifrada con clave = " + clave + " ->" + cifrar(texto, clave) + "<-");
                break;
                case 2:
                    System.out.printf("1. Introduzca el texto cifradon> ");
                    texto = consola.readLine();
                    System.out.printf("2. Introduzca la clave con la que codificó el texton> ");
                    clave = lee.nextInt();
                    System.out.println("3. Cadena cifrada con clave = " + clave + " ->" + descifrar(texto, clave) + "<-");
                break;
                default:System.out.println("3. Ha introducido una opción no válida. Pruebe de nuevo.");
            }
        }
    }

    static String cifrar(String original, int clave){
        // Inicializado con el tamaño de la cadena original. STRING SON INMUTABLES!
        StringBuilder cifrado = new StringBuilder(original.length());
        int valorASCII = 0;
        for(int i = 0;i < original.length(); i++){
            // 1 Guardamos el valor ASCII (31 - 126) del caracter número i
            valorASCII = (int)(original.charAt(i));

            // 2 Aplicamos la fórmula
            valorASCII = valorASCII + clave % 255;

            // 3 Añadimos el caracter cifrado
            cifrado.append((char)(valorASCII));
        }
        // 4 Devolvemos la conversión de StringBuilder a String
        return cifrado.toString();
    }

    static String descifrar(String original, int clave){
        // Proceso inverso del cifrado
        StringBuilder descifrado = new StringBuilder(original.length());
        int ASCIIcifrado = 0, n = 0;
        for(int i = 0;i < original.length(); i++){
            ASCIIcifrado = (int)(original.charAt(i));
            ASCIIcifrado = ASCIIcifrado - clave % 255;
            descifrado.append((char)(ASCIIcifrado));
        }
        return descifrado.toString();
    }
}

Versión segunda

/**
 * Created by erwol on 04/03/2016 at 13:55
 * For further information visit http://www.archecode.org
 */
import java.util.Scanner;
import java.io.Console;
public class Cesar_simplificado {
    private static Scanner lee = new Scanner(System.in);

    public static void main(String args[]){
        int op = -1;
        String texto = null;
        Console consola = System.console();
        int clave = 0;
        while(op != 0){
            System.out.print("ntCIFRADO CÉSARn0.- Salirn1.- Cifrarn2.- Descifrarn> ");
            op = lee.nextInt();
            switch(op){
                case 0:break;
                case 1:
                    System.out.printf("1. Introduzca el texto a cifrarn> ");
                    texto = consola.readLine();
                    System.out.printf("2. Introduzca la clave con la que se codificará el texton>");
                    clave = lee.nextInt();
                    System.out.println("3. Cadena cifrada con clave = " + clave + " ->" + cifrar(texto, clave) + "<-");
                    break;
                case 2:
                    System.out.printf("1. Introduzca el texto cifradon> ");
                    texto = consola.readLine();
                    System.out.printf("2. Introduzca la clave con la que codificó el texton> ");
                    clave = lee.nextInt();
                    System.out.println("3. Cadena cifrada con clave = " + clave + " ->" + descifrar(texto, clave) + "<-");
                    break;
                default:System.out.println("Ha introducido una opción no válida. Pruebe de nuevo.");
            }
        }
    }

    static String cifrar(String original, int clave){
        StringBuilder cifrado = new StringBuilder(original.length());
        for(int i = 0;i < original.length(); i++)
            cifrado.append((char)((int)(original.charAt(i)) + clave % 255));
        return cifrado.toString();
    }

    static String descifrar(String original, int clave){
        StringBuilder descifrado = new StringBuilder(original.length());
        for(int i = 0;i < original.length(); i++)
            descifrado.append((char)((int)(original.charAt(i)) - clave % 255));
        return descifrado.toString();
    }
}

9 comentarios en “Cifrado César escrito en Java

    1. Buenas Sha, ¡gracias por el aviso! Efectivamente, no está declarada, se traspapelaría. Debería estar declarada de forma, por ejemplo, local a la función con un valor inicial -1:
      int ok = -1;
      De todas formas te comento que estoy revisando el código, que en breve actualizaré. También subiré un artículo en el que explicaré el modo de incrustar este algoritmo en una interfaz gráfica con xswing. Saludos!

      1. Me da el mismo error, te dejo tal cual como dice aquí abajo.

        0.- Salir
        1.- Cifrar
        2.- Descifrar
        > 1
        1. Introduzca el texto a cifrar
        > Exception in thread “main” java.lang.NullPointerException
        at cifradoCesar.result.main(result.java:22)

        Después traté de cambiar el ‘consola’ por un Scanner común pero da otro ‘error’ de ejecución
        (Lo que pasa es que se salta el paso donde pongo el texto):

        CIFRADO CÉSAR
        0.- Salir
        1.- Cifrar
        2.- Descifrar
        > 1
        1. Introduzca el texto a cifrar
        > 2. Introduzca la clave con la que se codificará el texto
        >

        1. Buenas, a mi me funciona correctamente desde linux y windows siempre y cuando se ejecuta desde una terminal ~consola.

          Prueba Cesar

          El ‘problema’ que tienes con la clase Scanner es debido al buffer I/O, que a veces se come líneas ya que realmente no está pensado para hacer pruebas como estas en ‘bruto’. Lo tengo aclarado aquí: http://www.archecode.org/es/blog/introducir-texto-teclado-terminal-java/. En cualquier caso te recomiendo usar la clase Console siempre que te sea posible.

          Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.