Copia este código y pégalo en Sublime Text. Guárdalo como segurito.html y luego ábrelo en el navegador.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generador de Contraseñas Seguras</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
margin: 0;
padding: 0;
}
.container {
width: 90%;
max-width: 600px;
margin: 50px auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
h1 {
text-align: center;
color: #333;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
font-weight: bold;
}
.form-group input[type="range"], .form-group select {
width: 100%;
}
.form-group input[type="checkbox"] {
margin-right: 8px;
}
.form-group button {
width: 100%;
padding: 10px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.form-group button:hover {
background-color: #0056b3;
}
.password-output {
margin-top: 20px;
text-align: center;
}
.password-output p {
font-size: 18px;
font-weight: bold;
}
.strength {
margin-top: 10px;
font-weight: normal;
}
</style>
</head>
<body>
<div class="container">
<h1>Generador de Contraseñas Seguras</h1>
<!-- Formulario de personalización -->
<div class="form-group">
<label for="length">Longitud de la contraseña (número de palabras):</label>
<input type="range" id="length" min="4" max="12" value="6">
<p>Longitud: <span id="length-value">6</span> palabras</p>
</div>
<div class="form-group">
<label for="special">Incluir caracteres especiales (@, #, $, etc.):</label>
<input type="checkbox" id="special">
</div>
<div class="form-group">
<label for="numbers">Incluir números:</label>
<input type="checkbox" id="numbers">
</div>
<div class="form-group">
<label for="uppercase">Incluir mayúsculas:</label>
<input type="checkbox" id="uppercase">
</div>
<div class="form-group">
<button id="generate">Generar Contraseña</button>
</div>
<!-- Mostrar contraseñas generadas -->
<div class="password-output">
<p id="generated-password">Esperando a generar contraseña...</p>
<p id="password-strength" class="strength">Fortaleza: No evaluada</p>
</div>
</div>
<script>
const spanishWords = [
'sol', 'luna', 'cielo', 'río', 'montaña', 'viento', 'flor', 'luz', 'cielo', 'estrella', 'bosque', 'mar',
'ciudad', 'lago', 'nube', 'agua', 'fuego', 'piedra', 'árbol', 'flor', 'puente', 'camino', 'libertad', 'paz'
];
const lengthInput = document.getElementById('length');
const specialInput = document.getElementById('special');
const numbersInput = document.getElementById('numbers');
const uppercaseInput = document.getElementById('uppercase');
const generateButton = document.getElementById('generate');
const generatedPasswordEl = document.getElementById('generated-password');
const passwordStrengthEl = document.getElementById('password-strength');
const lengthValueEl = document.getElementById('length-value');
// Función para generar una pass-phrase aleatoria
function generatePassword() {
const length = lengthInput.value;
const includeSpecial = specialInput.checked;
const includeNumbers = numbersInput.checked;
const includeUppercase = uppercaseInput.checked;
let password = generatePassPhrase(length);
if (includeSpecial) {
password = addSpecialChars(password);
}
if (includeNumbers) {
password = addNumbers(password);
}
if (includeUppercase) {
password = addUppercase(password);
}
const strength = evaluateStrength(password);
generatedPasswordEl.textContent = password;
passwordStrengthEl.textContent = `Fortaleza: ${strength}`;
// Almacenamiento temporal en localStorage
localStorage.setItem('generatedPassword', password);
}
// Genera una pass-phrase aleatoria a partir del conjunto de palabras
function generatePassPhrase(length) {
let phrase = '';
for (let i = 0; i < length; i++) {
const randomWord = spanishWords[Math.floor(Math.random() * spanishWords.length)];
phrase += randomWord + ' ';
}
return phrase.trim();
}
// Añadir caracteres especiales aleatorios
function addSpecialChars(password) {
const specialChars = ['@', '#', '$', '%', '&', '*', '!', '?'];
const randomSpecialChar = specialChars[Math.floor(Math.random() * specialChars.length)];
const position = Math.floor(Math.random() * password.length);
return password.slice(0, position) + randomSpecialChar + password.slice(position);
}
// Añadir números aleatorios
function addNumbers(password) {
const randomNum = Math.floor(Math.random() * 10);
const position = Math.floor(Math.random() * password.length);
return password.slice(0, position) + randomNum + password.slice(position);
}
// Añadir mayúsculas aleatorias
function addUppercase(password) {
const randomIndex = Math.floor(Math.random() * password.length);
return password.slice(0, randomIndex) + password.charAt(randomIndex).toUpperCase() + password.slice(randomIndex + 1);
}
// Evaluar la fortaleza de la contraseña
function evaluateStrength(password) {
const lengthCriteria = password.length > 20 ? 'Muy segura' : password.length > 15 ? 'Segura' : 'Débil';
const specialCharCriteria = /[!@#$%^&*()_+{}\[\]:;"'<>,.?\\/-]/.test(password) ? 1 : 0;
const numberCriteria = /\d/.test(password) ? 1 : 0;
const uppercaseCriteria = /[A-Z]/.test(password) ? 1 : 0;
let score = password.length > 15 ? 2 : 0;
score += specialCharCriteria;
score += numberCriteria;
score += uppercaseCriteria;
if (score >= 4) return 'Muy segura';
if (score >= 3) return 'Segura';
return 'Débil';
}
// Actualizar el valor de longitud en el HTML
lengthInput.addEventListener('input', () => {
lengthValueEl.textContent = lengthInput.value;
});
// Generar contraseña al hacer clic en el botón
generateButton.addEventListener('click', generatePassword);
// Recuperar la contraseña generada del localStorage
if (localStorage.getItem('generatedPassword')) {
generatedPasswordEl.textContent = localStorage.getItem('generatedPassword');
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generador de Contraseñas Seguras</title>
<style>
:root {
--bg-color: #f5f5f5;
--text-color: #333;
--primary-color: #4a6fa5;
--secondary-color: #6c757d;
--success-color: #28a745;
--warning-color: #ffc107;
--danger-color: #dc3545;
--card-bg: #fff;
--border-color: #ddd;
}
[data-theme="dark"] {
--bg-color: #121212;
--text-color: #f5f5f5;
--primary-color: #6c8fc7;
--secondary-color: #5a6268;
--card-bg: #1e1e1e;
--border-color: #444;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
padding: 20px;
transition: all 0.3s ease;
}
.container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.card {
background-color: var(--card-bg);
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
padding: 25px;
margin-bottom: 20px;
border: 1px solid var(--border-color);
}
h1 {
color: var(--primary-color);
text-align: center;
margin-bottom: 25px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 600;
}
select, input[type="range"], input[type="number"], button {
width: 100%;
padding: 10px;
border-radius: 5px;
border: 1px solid var(--border-color);
background-color: var(--card-bg);
color: var(--text-color);
}
button {
background-color: var(--primary-color);
color: white;
border: none;
cursor: pointer;
font-weight: bold;
margin-top: 10px;
transition: background-color 0.3s;
}
button:hover {
background-color: #3a5a80;
}
.result-container {
margin-top: 20px;
position: relative;
}
.password-result {
font-size: 1.2rem;
word-break: break-all;
padding: 15px;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 5px;
border: 1px dashed var(--border-color);
}
.strength-meter {
height: 5px;
background-color: var(--secondary-color);
border-radius: 5px;
margin-top: 10px;
overflow: hidden;
}
.strength-bar {
height: 100%;
width: 0%;
transition: width 0.3s, background-color 0.3s;
}
.copy-btn {
position: absolute;
right: 10px;
top: 10px;
background-color: var(--secondary-color);
padding: 5px 10px;
font-size: 0.8rem;
width: auto;
}
.copy-btn:hover {
background-color: #5a6268;
}
.settings-toggle {
color: var(--primary-color);
text-decoration: underline;
cursor: pointer;
font-size: 0.9rem;
margin-bottom: 15px;
display: inline-block;
}
.settings-panel {
display: none;
margin-top: 15px;
padding: 15px;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 5px;
}
.settings-panel.show {
display: block;
}
.toggle-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: var(--primary-color);
}
input:checked + .slider:before {
transform: translateX(26px);
}
.history-item {
padding: 10px;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
}
.history-item:last-child {
border-bottom: none;
}
.controls {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.font-size-controls button {
width: auto;
padding: 5px 10px;
margin-right: 5px;
}
@media (max-width: 480px) {
.container {
padding: 10px;
}
.card {
padding: 15px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<h1>Generador de Contraseñas Seguras</h1>
<div class="form-group">
<label for="password-type">Tipo de contraseña:</label>
<select id="password-type">
<option value="random">Contraseña aleatoria</option>
<option value="phrase">Pass-phrase en español</option>
</select>
</div>
<div id="random-settings">
<div class="form-group">
<label for="length">Longitud: <span id="length-value">12</span> caracteres</label>
<input type="range" id="length" min="8" max="64" value="12">
</div>
</div>
<div id="phrase-settings" style="display: none;">
<div class="form-group">
<label for="word-count">Número de palabras: <span id="word-count-value">4</span></label>
<input type="range" id="word-count" min="3" max="8" value="4">
</div>
</div>
<span class="settings-toggle" id="toggle-settings">Mostrar opciones avanzadas</span>
<div class="settings-panel" id="advanced-settings">
<div class="form-group">
<label>
<input type="checkbox" id="uppercase" checked>
Incluir mayúsculas
</label>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="numbers" checked>
Incluir números
</label>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="symbols" checked>
Incluir símbolos
</label>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="avoid-ambiguous">
Evitar caracteres ambiguos (l,1,0,O)
</label>
</div>
</div>
<button id="generate-btn">Generar Contraseña</button>
<div class="result-container">
<div class="password-result" id="password-result">Tu contraseña aparecerá aquí...</div>
<button class="copy-btn" id="copy-btn">Copiar</button>
<div class="strength-meter">
<div class="strength-bar" id="strength-bar"></div>
</div>
<div id="strength-text" style="text-align: center; margin-top: 5px;"></div>
</div>
</div>
<div class="card">
<h2>Historial</h2>
<div id="password-history"></div>
<div class="controls">
<div class="font-size-controls">
<button id="font-small">A-</button>
<button id="font-medium">A</button>
<button id="font-large">A+</button>
</div>
<button id="clear-history">Limpiar historial</button>
</div>
</div>
<div class="toggle-container">
<span>Modo oscuro</span>
<label class="switch">
<input type="checkbox" id="theme-toggle">
<span class="slider"></span>
</label>
</div>
</div>
<script>
// Palabras en español para pass-phrases
const spanishWords = [
'casa', 'perro', 'gato', 'sol', 'luna', 'árbol', 'agua', 'fuego', 'tierra', 'aire',
'libro', 'mano', 'pie', 'ojo', 'boca', 'nariz', 'cielo', 'mar', 'rio', 'montaña',
'flor', 'hoja', 'piedra', 'arena', 'nube', 'lluvia', 'viento', 'nieve', 'estrella',
'pan', 'leche', 'queso', 'fruta', 'verde', 'azul', 'rojo', 'amarillo', 'blanco', 'negro',
'grande', 'pequeño', 'feliz', 'triste', 'rápido', 'lento', 'caliente', 'frío', 'nuevo', 'viejo',
'uno', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve', 'diez',
'camino', 'puerta', 'ventana', 'silla', 'mesa', 'cama', 'reloj', 'espejo', 'llave', 'corazón',
'amigo', 'familia', 'trabajo', 'escuela', 'juego', 'música', 'arte', 'tiempo', 'amor', 'paz'
];
// Símbolos disponibles
const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
// Elementos del DOM
const passwordType = document.getElementById('password-type');
const randomSettings = document.getElementById('random-settings');
const phraseSettings = document.getElementById('phrase-settings');
const lengthInput = document.getElementById('length');
const lengthValue = document.getElementById('length-value');
const wordCountInput = document.getElementById('word-count');
const wordCountValue = document.getElementById('word-count-value');
const uppercaseCheckbox = document.getElementById('uppercase');
const numbersCheckbox = document.getElementById('numbers');
const symbolsCheckbox = document.getElementById('symbols');
const avoidAmbiguousCheckbox = document.getElementById('avoid-ambiguous');
const generateBtn = document.getElementById('generate-btn');
const passwordResult = document.getElementById('password-result');
const copyBtn = document.getElementById('copy-btn');
const strengthBar = document.getElementById('strength-bar');
const strengthText = document.getElementById('strength-text');
const toggleSettings = document.getElementById('toggle-settings');
const advancedSettings = document.getElementById('advanced-settings');
const passwordHistory = document.getElementById('password-history');
const clearHistoryBtn = document.getElementById('clear-history');
const fontSmallBtn = document.getElementById('font-small');
const fontMediumBtn = document.getElementById('font-medium');
const fontLargeBtn = document.getElementById('font-large');
const themeToggle = document.getElementById('theme-toggle');
// Cambiar entre tipos de contraseña
passwordType.addEventListener('change', function() {
if (this.value === 'random') {
randomSettings.style.display = 'block';
phraseSettings.style.display = 'none';
} else {
randomSettings.style.display = 'none';
phraseSettings.style.display = 'block';
}
});
// Actualizar valores de los sliders
lengthInput.addEventListener('input', function() {
lengthValue.textContent = this.value;
});
wordCountInput.addEventListener('input', function() {
wordCountValue.textContent = this.value;
});
// Mostrar/ocultar opciones avanzadas
toggleSettings.addEventListener('click', function() {
advancedSettings.classList.toggle('show');
this.textContent = advancedSettings.classList.contains('show') ?
'Ocultar opciones avanzadas' : 'Mostrar opciones avanzadas';
});
// Generar contraseña
generateBtn.addEventListener('click', function() {
let password = '';
const type = passwordType.value;
if (type === 'random') {
password = generateRandomPassword();
} else {
password = generatePassPhrase();
}
passwordResult.textContent = password;
checkPasswordStrength(password);
saveToHistory(password);
});
// Generar contraseña aleatoria
function generateRandomPassword() {
const length = parseInt(lengthInput.value);
const includeUppercase = uppercaseCheckbox.checked;
const includeNumbers = numbersCheckbox.checked;
const includeSymbols = symbolsCheckbox.checked;
const avoidAmbiguous = avoidAmbiguousCheckbox.checked;
let charset = 'abcdefghijklmnopqrstuvwxyz';
if (includeUppercase) charset += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (includeNumbers) charset += '0123456789';
if (includeSymbols) charset += symbols;
if (avoidAmbiguous) {
charset = charset.replace(/[l1O0]/g, '');
}
let password = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charset.length);
password += charset[randomIndex];
}
return password;
}
// Generar pass-phrase
function generatePassPhrase() {
const wordCount = parseInt(wordCountInput.value);
const includeNumbers = numbersCheckbox.checked;
const includeSymbols = symbolsCheckbox.checked;
let phrase = '';
// Seleccionar palabras aleatorias
for (let i = 0; i < wordCount; i++) {
const randomIndex = Math.floor(Math.random() * spanishWords.length);
phrase += spanishWords[randomIndex];
if (i < wordCount - 1) {
phrase += '-';
}
}
// Añadir número al final si está seleccionado
if (includeNumbers) {
const randomNumber = Math.floor(Math.random() * 90) + 10; // Número entre 10-99
phrase += randomNumber;
}
// Añadir símbolo si está seleccionado
if (includeSymbols) {
const randomSymbol = symbols[Math.floor(Math.random() * symbols.length)];
phrase += randomSymbol;
}
return phrase;
}
// Verificar fortaleza de la contraseña
function checkPasswordStrength(password) {
let strength = 0;
const length = password.length;
// Longitud
if (length > 12) strength += 2;
else if (length > 8) strength += 1;
// Tipos de caracteres
if (/[A-Z]/.test(password)) strength += 1;
if (/[0-9]/.test(password)) strength += 1;
if (/[^A-Za-z0-9]/.test(password)) strength += 1;
// Pass-phrases son más fuertes
if (password.includes('-')) strength += 2;
// Actualizar UI
let strengthPercent = 0;
let strengthLabel = '';
let strengthColor = '';
if (strength <= 2) {
strengthPercent = 33;
strengthLabel = 'Débil';
strengthColor = 'var(--danger-color)';
} else if (strength <= 4) {
strengthPercent = 66;
strengthLabel = 'Media';
strengthColor = 'var(--warning-color)';
} else {
strengthPercent = 100;
strengthLabel = 'Fuerte';
strengthColor = 'var(--success-color)';
}
strengthBar.style.width = strengthPercent + '%';
strengthBar.style.backgroundColor = strengthColor;
strengthText.textContent = 'Fortaleza: ' + strengthLabel;
strengthText.style.color = strengthColor;
}
// Copiar al portapapeles
copyBtn.addEventListener('click', function() {
const password = passwordResult.textContent;
if (password && password !== 'Tu contraseña aparecerá aquí...') {
navigator.clipboard.writeText(password).then(function() {
const originalText = copyBtn.textContent;
copyBtn.textContent = '¡Copiado!';
setTimeout(function() {
copyBtn.textContent = originalText;
}, 2000);
});
}
});
// Guardar en historial
function saveToHistory(password) {
if (!password || password === 'Tu contraseña aparecerá aquí...') return;
const historyItem = document.createElement('div');
historyItem.className = 'history-item';
const passwordSpan = document.createElement('span');
passwordSpan.textContent = password;
const copySpan = document.createElement('span');
copySpan.textContent = 'Copiar';
copySpan.style.color = 'var(--primary-color)';
copySpan.style.cursor = 'pointer';
copySpan.addEventListener('click', function() {
navigator.clipboard.writeText(password);
copySpan.textContent = '¡Copiado!';
setTimeout(function() {
copySpan.textContent = 'Copiar';
}, 2000);
});
historyItem.appendChild(passwordSpan);
historyItem.appendChild(copySpan);
// Insertar al principio
if (passwordHistory.firstChild) {
passwordHistory.insertBefore(historyItem, passwordHistory.firstChild);
} else {
passwordHistory.appendChild(historyItem);
}
// Guardar en localStorage
let history = JSON.parse(localStorage.getItem('passwordHistory') || '[]');
history.unshift(password);
if (history.length > 10) history = history.slice(0, 10);
localStorage.setItem('passwordHistory', JSON.stringify(history));
}
// Cargar historial al iniciar
function loadHistory() {
const history = JSON.parse(localStorage.getItem('passwordHistory') || '[]');
history.forEach(password => {
const historyItem = document.createElement('div');
historyItem.className = 'history-item';
const passwordSpan = document.createElement('span');
passwordSpan.textContent = password;
const copySpan = document.createElement('span');
copySpan.textContent = 'Copiar';
copySpan.style.color = 'var(--primary-color)';
copySpan.style.cursor = 'pointer';
copySpan.addEventListener('click', function() {
navigator.clipboard.writeText(password);
copySpan.textContent = '¡Copiado!';
setTimeout(function() {
copySpan.textContent = 'Copiar';
}, 2000);
});
historyItem.appendChild(passwordSpan);
historyItem.appendChild(copySpan);
passwordHistory.appendChild(historyItem);
});
}
// Limpiar historial
clearHistoryBtn.addEventListener('click', function() {
passwordHistory.innerHTML = '';
localStorage.removeItem('passwordHistory');
});
// Control de tamaño de fuente
fontSmallBtn.addEventListener('click', function() {
document.body.style.fontSize = '14px';
});
fontMediumBtn.addEventListener('click', function() {
document.body.style.fontSize = '16px';
});
fontLargeBtn.addEventListener('click', function() {
document.body.style.fontSize = '18px';
});
// Tema oscuro/claro
themeToggle.addEventListener('change', function() {
if (this.checked) {
document.documentElement.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
} else {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem('theme', 'light');
}
});
// Cargar tema guardado
const savedTheme = localStorage.getItem('theme') || 'light';
if (savedTheme === 'dark') {
themeToggle.checked = true;
document.documentElement.setAttribute('data-theme', 'dark');
}
// Cargar historial al iniciar
loadHistory();
// Generar una contraseña al cargar la página
generateBtn.click();
</script>
</body>
</html>