Cifrado César en JavaScript - Guía Paso a Paso

anuncio

Acerca de Este Tutorial

JavaScript es el lenguaje ideal para crear herramientas de cifrado interactivas que se ejecutan directamente en el navegador. Este tutorial completo te guiará a través de la implementación del cifrado César en JavaScript, desde funciones básicas hasta aplicaciones web interactivas con manipulación del DOM. Ya sea que estés creando herramientas educativas o aprendiendo conceptos de criptografía, esta guía cubre todo lo que necesitas. Antes de sumergirte en el código, revisa nuestra Guía para Principiantes del Cifrado César para comprender los fundamentos del cifrado.

Entendiendo los Fundamentos

El cifrado César desplaza cada letra del texto plano un número fijo de posiciones en el alfabeto. En JavaScript, utilizaremos métodos de código de caracteres y aritmética modular para implementar esto eficientemente tanto en navegadores como en entornos Node.js.

Ejemplo:

Con un desplazamiento de 3, "HELLO" se convierte en "KHOOR"

Implementación Básica en JavaScript

Comencemos con una función de cifrado sencilla que demuestra el concepto principal:

function caesarEncrypt(text, shift) {
    /**
     * Encrypts text using Caesar cipher with given shift value.
     *
     * @param {string} text - Text to encrypt
     * @param {number} shift - Number of positions to shift (1-25)
     * @returns {string} Encrypted text
     */
    let result = '';

    for (let i = 0; i < text.length; i++) {
        let char = text[i];

        // Check if character is uppercase letter
        if (char >= 'A' && char <= 'Z') {
            // Shift within uppercase letters (A-Z)
            let code = text.charCodeAt(i);
            char = String.fromCharCode(((code - 65 + shift) % 26) + 65);
        }
        // Check if character is lowercase letter
        else if (char >= 'a' && char <= 'z') {
            // Shift within lowercase letters (a-z)
            let code = text.charCodeAt(i);
            char = String.fromCharCode(((code - 97 + shift) % 26) + 97);
        }
        // Keep non-alphabetic characters unchanged

        result += char;
    }

    return result;
}

// Example usage
const plaintext = "Hello World!";
const shift = 3;
const encrypted = caesarEncrypt(plaintext, shift);
console.log(`Original: ${plaintext}`);
console.log(`Encrypted: ${encrypted}`);

// Output:
// Original: Hello World!
// Encrypted: Khoor Zruog!

Cómo Funciona la Implementación en JavaScript

Entendiendo los métodos clave de JavaScript utilizados en el cifrado César:

Método charCodeAt()

Devuelve el valor Unicode de un carácter. Para 'A', 'A'.charCodeAt(0) retorna 65. Esto es esencial para convertir letras a números.

String.fromCharCode()

Convierte valores Unicode de vuelta a caracteres. String.fromCharCode(65) retorna 'A'. Se usa para reconstruir la cadena cifrada.

Aritmética Modular (% 26)

El operador módulo envuelve las letras alrededor del alfabeto. Cuando 'Z' + 1 excede el alfabeto, vuelve a 'A'. Es fundamental para mantener los límites alfabéticos.

Métodos de Arrays

split(), map() y join() permiten un estilo de programación funcional, haciendo el código más legible y mantenible.

Implementación Moderna con ES6+

Utilizando características modernas de JavaScript para un código más limpio y funcional:

const caesarCipher = (text, shift) => {
    /**
     * Modern ES6+ Caesar cipher implementation
     */
    const encrypt = (char) => {
        if (!/[a-zA-Z]/.test(char)) return char;

        const base = char === char.toUpperCase() ? 65 : 97;
        return String.fromCharCode(
            ((char.charCodeAt(0) - base + shift) % 26) + base
        );
    };

    return text.split('').map(encrypt).join('');
};

const decrypt = (text, shift) => caesarCipher(text, -shift);

// Example usage with arrow functions
const message = "JavaScript is powerful!";
const encrypted = caesarCipher(message, 7);
const decrypted = decrypt(encrypted, 7);

console.log(`Original: ${message}`);
console.log(`Encrypted: ${encrypted}`);
console.log(`Decrypted: ${decrypted}`);

Integración en el Navegador con DOM

Crea una herramienta interactiva de cifrado César que los usuarios pueden usar directamente en su navegador. Aquí tienes un ejemplo completo con HTML y JavaScript:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Herramienta de Cifrado César</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
        }
        .input-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }
        input, textarea {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        button {
            background: #4f46e5;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-right: 10px;
        }
        button:hover {
            background: #4338ca;
        }
        #result {
            margin-top: 20px;
            padding: 15px;
            background: #f3f4f6;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <h1>Herramienta de Cifrado César</h1>

    <div class="input-group">
        <label for="text">Introduce el Texto:</label>
        <textarea id="text" rows="4" placeholder="Escribe tu mensaje aquí..."></textarea>
    </div>

    <div class="input-group">
        <label for="shift">Valor de Desplazamiento (1-25):</label>
        <input type="number" id="shift" min="1" max="25" value="3">
    </div>

    <button onclick="encrypt()">Cifrar</button>
    <button onclick="decrypt()">Descifrar</button>

    <div id="result"></div>

    <script src="caesar.js"></script>
</body>
</html>
// caesar.js - DOM manipulation for Caesar cipher tool

function caesarTransform(text, shift) {
    return text.split('').map(char => {
        if (char >= 'A' && char <= 'Z') {
            return String.fromCharCode(((char.charCodeAt(0) - 65 + shift) % 26) + 65);
        }
        if (char >= 'a' && char <= 'z') {
            return String.fromCharCode(((char.charCodeAt(0) - 97 + shift) % 26) + 97);
        }
        return char;
    }).join('');
}

function encrypt() {
    const text = document.getElementById('text').value;
    const shift = parseInt(document.getElementById('shift').value);

    if (!text) {
        alert('Por favor introduce texto para cifrar');
        return;
    }

    const result = caesarTransform(text, shift);
    displayResult('Cifrado', result);
}

function decrypt() {
    const text = document.getElementById('text').value;
    const shift = parseInt(document.getElementById('shift').value);

    if (!text) {
        alert('Por favor introduce texto para descifrar');
        return;
    }

    const result = caesarTransform(text, -shift);
    displayResult('Descifrado', result);
}

function displayResult(operation, text) {
    const resultDiv = document.getElementById('result');
    resultDiv.innerHTML = `
        <h3>Resultado ${operation}:</h3>
        <p><strong>${text}</strong></p>
        <button onclick="copyToClipboard('${text.replace(/'/g, "\\'")}')" style="margin-top: 10px;">
            Copiar al Portapapeles
        </button>
    `;
}

function copyToClipboard(text) {
    navigator.clipboard.writeText(text).then(() => {
        alert('Copiado al portapapeles!');
    }).catch(err => {
        console.error('Error al copiar:', err);
    });
}

Implementación Avanzada Basada en Clases

Para aplicaciones en producción, un enfoque basado en clases proporciona mejor organización y reutilización:

class CaesarCipher {
    /**
     * Comprehensive Caesar cipher implementation with advanced features
     */

    constructor(shift = 3) {
        this.shift = ((shift % 26) + 26) % 26; // Handle negative shifts
    }

    encrypt(text) {
        return this.transform(text, this.shift);
    }

    decrypt(text) {
        return this.transform(text, -this.shift);
    }

    transform(text, shift) {
        return text.split('').map(char => {
            if (!/[a-zA-Z]/.test(char)) return char;

            const base = char === char.toUpperCase() ? 65 : 97;
            return String.fromCharCode(
                ((char.charCodeAt(0) - base + shift + 26) % 26) + base
            );
        }).join('');
    }

    bruteForce(encryptedText) {
        /**
         * Try all possible shifts to decrypt text
         * Useful when the shift is unknown
         *
         * @param {string} encryptedText - Text to decrypt
         * @returns {Array} All 26 possible decryptions
         */
        const results = [];
        for (let shift = 0; shift < 26; shift++) {
            results.push({
                shift,
                text: this.transform(encryptedText, -shift)
            });
        }
        return results;
    }

    setShift(newShift) {
        this.shift = ((newShift % 26) + 26) % 26;
        return this;
    }

    static rot13(text) {
        // ROT13 is Caesar cipher with shift of 13
        return new CaesarCipher(13).encrypt(text);
    }
}

// Example usage
const cipher = new CaesarCipher(5);

// Encryption
const message = "JavaScript es increíble!";
const encrypted = cipher.encrypt(message);
console.log(`Original: ${message}`);
console.log(`Encrypted: ${encrypted}`);

// Decryption
const decrypted = cipher.decrypt(encrypted);
console.log(`Decrypted: ${decrypted}`);

// Brute force attack
const mysteryText = "Mjqqt Btwqi";
console.log("\nResultados de fuerza bruta:");
cipher.bruteForce(mysteryText).slice(0, 5).forEach(result => {
    console.log(`Shift ${result.shift}: ${result.text}`);
});

// ROT13
const rot13Text = CaesarCipher.rot13("Hello World");
console.log(`\nROT13: ${rot13Text}`);

Mejores Prácticas de JavaScript

Nuestra implementación sigue estándares modernos de JavaScript y mejores prácticas:

  • Comentarios JSDoc: Documentación clara explicando parámetros, tipos de retorno y propósito de las funciones
  • Características ES6+: Funciones flecha, plantillas literales y const/let para sintaxis moderna
  • Validación de Entrada: Verificar cadenas vacías y validar valores de desplazamiento
  • Enfoque Funcional: Funciones puras sin efectos secundarios para mejor testabilidad
  • Principio DRY: El método de transformación reutilizable elimina la duplicación de código
  • Encapsulación de Clases: Diseño orientado a objetos para funcionalidad relacionada

Errores Comunes a Evitar

Cuidado con estos errores frecuentes al implementar el cifrado César en JavaScript:

  • Olvidar el Módulo: Sin % 26, los códigos de caracteres pueden exceder el rango válido
  • Desplazamientos Negativos: Añade 26 antes del módulo para manejar valores negativos correctamente
  • Sensibilidad de Mayúsculas: Maneja letras mayúsculas y minúsculas con diferentes valores base
  • Caracteres No Alfabéticos: Preserva espacios, puntuación y números sin cambios
  • Coerción de Tipos: Asegúrate de que el valor de desplazamiento se convierta a número con parseInt()

Uso del Cifrado César en Node.js

La misma implementación funciona perfectamente en Node.js para cifrado del lado del servidor, herramientas de línea de comandos o procesamiento de archivos:

// Node.js Caesar cipher implementation
// Save as caesar-cli.js

const readline = require('readline');

class CaesarCipher {
    constructor(shift = 3) {
        this.shift = ((shift % 26) + 26) % 26;
    }

    encrypt(text) {
        return this.transform(text, this.shift);
    }

    decrypt(text) {
        return this.transform(text, -this.shift);
    }

    transform(text, shift) {
        return text.split('').map(char => {
            if (!/[a-zA-Z]/.test(char)) return char;
            const base = char === char.toUpperCase() ? 65 : 97;
            return String.fromCharCode(
                ((char.charCodeAt(0) - base + shift + 26) % 26) + base
            );
        }).join('');
    }
}

// Command-line interface
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

console.log('=== Herramienta CLI de Cifrado César ===\n');

rl.question('Introduce el texto: ', (text) => {
    rl.question('Introduce el valor de desplazamiento: ', (shift) => {
        rl.question('¿Cifrar o Descifrar? (c/d): ', (operation) => {
            const cipher = new CaesarCipher(parseInt(shift));
            const result = operation.toLowerCase() === 'c'
                ? cipher.encrypt(text)
                : cipher.decrypt(text);

            console.log(`\nResultado: ${result}\n`);
            rl.close();
        });
    });
});

// Export for use as module
module.exports = CaesarCipher;

Casos de Uso Prácticos

Las implementaciones del cifrado César en JavaScript son perfectas para:

Herramientas educativas interactivas y demostraciones
Plataformas de aprendizaje de criptografía basadas en navegador
Ofuscación simple de mensajes en aplicaciones web
Soluciones de desafíos de programación y práctica de entrevistas
Construcción de base para sistemas de cifrado más complejos
Creación de juegos de puzzles y herramientas de escape rooms

Consideraciones de Rendimiento

La implementación tiene complejidad temporal O(n) donde n es la longitud del texto. Para un rendimiento óptimo:

  • Usa map() y join() en lugar de concatenación de cadenas en bucles
  • Precompila expresiones regulares fuera de las funciones cuando se usen repetidamente
  • Considera las APIs TextEncoder/TextDecoder para procesamiento de texto grande
  • Usa Web Workers para cifrar archivos grandes sin bloquear la UI
  • Cachea alfabetos cifrados al procesar múltiples mensajes con el mismo desplazamiento

Probando Tu Implementación

Casos de prueba completos para verificar que tu cifrado César funcione correctamente:

// Test suite for Caesar cipher (using Jest or similar)

describe('Caesar Cipher Tests', () => {
    const cipher = new CaesarCipher(3);

    test('encrypts basic text correctly', () => {
        expect(cipher.encrypt('ABC')).toBe('DEF');
    });

    test('handles wrap around from Z to A', () => {
        expect(cipher.encrypt('XYZ')).toBe('ABC');
    });

    test('preserves case', () => {
        expect(cipher.encrypt('Hello')).toBe('Khoor');
    });

    test('keeps non-alphabetic characters unchanged', () => {
        expect(cipher.encrypt('Hello, World!')).toBe('Khoor, Zruog!');
    });

    test('encryption and decryption are reversible', () => {
        const original = 'JavaScript Programming';
        const encrypted = cipher.encrypt(original);
        const decrypted = cipher.decrypt(encrypted);
        expect(decrypted).toBe(original);
    });

    test('handles shift of 0', () => {
        const cipher0 = new CaesarCipher(0);
        expect(cipher0.encrypt('Test')).toBe('Test');
    });

    test('handles negative shifts', () => {
        const cipherNeg = new CaesarCipher(-3);
        expect(cipherNeg.encrypt('DEF')).toBe('ABC');
    });

    test('handles shifts greater than 26', () => {
        const cipher29 = new CaesarCipher(29);
        expect(cipher29.encrypt('ABC')).toBe('DEF'); // 29 % 26 = 3
    });

    test('ROT13 is self-inverse', () => {
        const text = 'Hello World';
        const rot13Once = CaesarCipher.rot13(text);
        const rot13Twice = CaesarCipher.rot13(rot13Once);
        expect(rot13Twice).toBe(text);
    });
});

console.log('All tests passed!');

Ideas de Mejora

Extiende esta implementación con características adicionales:

Añade visualización de análisis de frecuencia con Chart.js
Implementa detección automática de idioma
Crea componente wrapper para React o Vue
Añade localStorage para guardar historial de cifrado
Construye extensión de navegador para cifrar contenido web
Integra con Clipboard API para copiar/pegar fácilmente
Añade soporte para alfabetos personalizados y Unicode
Crea visualización animada del cifrado

Recursos Relacionados

Continúa tu viaje de aprendizaje de criptografía y JavaScript:

Resumen

Has aprendido cómo implementar el cifrado César en JavaScript desde funciones básicas hasta aplicaciones web interactivas. Hemos cubierto implementaciones clásicas, sintaxis moderna ES6+, manipulación del DOM, diseño basado en clases y uso en Node.js. Este conocimiento forma la base para construir herramientas de cifrado más sofisticadas y comprender la criptografía basada en web.

Practica creando tu propia herramienta de cifrado interactiva, experimenta con diferentes frameworks de UI o combina el cifrado César con otras técnicas de cifrado. Aunque el cifrado César no es adecuado para proteger datos sensibles, proporciona una excelente introducción a los conceptos criptográficos y la manipulación de cadenas en JavaScript para desarrolladores web.