Secure password manager with autofill capabilities
当前为
// ==UserScript==
// @name Password Manager & Autofiller
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Secure password manager with autofill capabilities
// @author voidofdarkness
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_listValues
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// Encryption/Decryption utilities (simple XOR - for production use a proper crypto library)
function simpleEncrypt(text, key) {
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return btoa(result);
}
function simpleDecrypt(encoded, key) {
const text = atob(encoded);
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return result;
}
// Get master password from user
let masterPassword = GM_getValue('master_password', '');
// Password storage functions
function savePassword(domain, username, password) {
if (!masterPassword) {
alert('Please set a master password first!');
return;
}
const encrypted = simpleEncrypt(password, masterPassword);
const key = `pwd_${domain}`;
const data = GM_getValue(key, {});
data[username] = encrypted;
GM_setValue(key, data);
}
function getPasswords(domain) {
if (!masterPassword) return {};
const key = `pwd_${domain}`;
const data = GM_getValue(key, {});
const decrypted = {};
for (let username in data) {
try {
decrypted[username] = simpleDecrypt(data[username], masterPassword);
} catch (e) {
console.error('Decryption failed for', username);
}
}
return decrypted;
}
function deletePassword(domain, username) {
const key = `pwd_${domain}`;
const data = GM_getValue(key, {});
delete data[username];
GM_setValue(key, data);
}
// Get current domain
const currentDomain = window.location.hostname;
// Create UI
function createUI() {
const panel = document.createElement('div');
panel.id = 'pwd-manager-panel';
panel.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
width: 320px;
background: #2c3e50;
color: #ecf0f1;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
z-index: 999999;
font-family: Arial, sans-serif;
display: none;
`;
panel.innerHTML = `
<div style="padding: 15px; border-bottom: 1px solid #34495e;">
<h3 style="margin: 0; font-size: 16px;">🔐 Password Manager</h3>
<button id="close-panel" style="position: absolute; top: 15px; right: 15px; background: none; border: none; color: #ecf0f1; font-size: 20px; cursor: pointer;">×</button>
</div>
<div style="padding: 15px;">
<div id="master-pwd-section" style="margin-bottom: 15px;">
<input type="password" id="master-pwd-input" placeholder="Master Password" style="width: 100%; padding: 8px; border: 1px solid #34495e; border-radius: 4px; background: #34495e; color: #ecf0f1; box-sizing: border-box;">
<button id="set-master-pwd" style="width: 100%; margin-top: 8px; padding: 8px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer;">Set Master Password</button>
</div>
<div id="password-section" style="display: none;">
<div style="margin-bottom: 15px;">
<strong>Domain:</strong> ${currentDomain}
</div>
<input type="text" id="username-input" placeholder="Username" style="width: 100%; padding: 8px; margin-bottom: 8px; border: 1px solid #34495e; border-radius: 4px; background: #34495e; color: #ecf0f1; box-sizing: border-box;">
<input type="password" id="password-input" placeholder="Password" style="width: 100%; padding: 8px; margin-bottom: 8px; border: 1px solid #34495e; border-radius: 4px; background: #34495e; color: #ecf0f1; box-sizing: border-box;">
<button id="save-pwd" style="width: 100%; padding: 8px; background: #27ae60; color: white; border: none; border-radius: 4px; cursor: pointer; margin-bottom: 15px;">Save Password</button>
<div id="saved-passwords" style="max-height: 200px; overflow-y: auto;">
<strong>Saved Accounts:</strong>
<div id="password-list" style="margin-top: 8px;"></div>
</div>
</div>
</div>
`;
document.body.appendChild(panel);
// Toggle button
const toggleBtn = document.createElement('button');
toggleBtn.id = 'pwd-manager-toggle';
toggleBtn.innerHTML = '🔐';
toggleBtn.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
width: 50px;
height: 50px;
border-radius: 50%;
background: #3498db;
color: white;
border: none;
font-size: 24px;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
z-index: 999998;
`;
document.body.appendChild(toggleBtn);
// Event listeners
toggleBtn.onclick = () => {
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
};
document.getElementById('close-panel').onclick = () => {
panel.style.display = 'none';
};
document.getElementById('set-master-pwd').onclick = () => {
const pwd = document.getElementById('master-pwd-input').value;
if (pwd.length < 4) {
alert('Master password must be at least 4 characters!');
return;
}
masterPassword = pwd;
GM_setValue('master_password', pwd);
document.getElementById('master-pwd-section').style.display = 'none';
document.getElementById('password-section').style.display = 'block';
updatePasswordList();
};
document.getElementById('save-pwd').onclick = () => {
const username = document.getElementById('username-input').value;
const password = document.getElementById('password-input').value;
if (!username || !password) {
alert('Please enter both username and password!');
return;
}
savePassword(currentDomain, username, password);
document.getElementById('username-input').value = '';
document.getElementById('password-input').value = '';
updatePasswordList();
alert('Password saved!');
};
if (masterPassword) {
document.getElementById('master-pwd-section').style.display = 'none';
document.getElementById('password-section').style.display = 'block';
updatePasswordList();
}
}
function updatePasswordList() {
const passwords = getPasswords(currentDomain);
const listDiv = document.getElementById('password-list');
listDiv.innerHTML = '';
if (Object.keys(passwords).length === 0) {
listDiv.innerHTML = '<div style="color: #95a5a6; font-size: 12px;">No saved passwords for this site</div>';
return;
}
for (let username in passwords) {
const itemDiv = document.createElement('div');
itemDiv.style.cssText = 'padding: 8px; background: #34495e; margin-bottom: 8px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center;';
itemDiv.innerHTML = `
<span style="flex: 1;">${username}</span>
<button class="autofill-btn" data-username="${username}" style="padding: 4px 8px; background: #3498db; color: white; border: none; border-radius: 3px; cursor: pointer; margin-right: 5px; font-size: 12px;">Fill</button>
<button class="delete-btn" data-username="${username}" style="padding: 4px 8px; background: #e74c3c; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px;">Delete</button>
`;
listDiv.appendChild(itemDiv);
}
// Autofill buttons
document.querySelectorAll('.autofill-btn').forEach(btn => {
btn.onclick = () => {
const username = btn.dataset.username;
const password = passwords[username];
autofillCredentials(username, password);
};
});
// Delete buttons
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.onclick = () => {
const username = btn.dataset.username;
if (confirm(`Delete password for ${username}?`)) {
deletePassword(currentDomain, username);
updatePasswordList();
}
};
});
}
function autofillCredentials(username, password) {
// Find username/email fields
const usernameFields = document.querySelectorAll('input[type="text"], input[type="email"], input[name*="user"], input[name*="email"], input[id*="user"], input[id*="email"]');
const passwordFields = document.querySelectorAll('input[type="password"]');
if (usernameFields.length > 0) {
usernameFields[0].value = username;
usernameFields[0].dispatchEvent(new Event('input', { bubbles: true }));
usernameFields[0].dispatchEvent(new Event('change', { bubbles: true }));
}
if (passwordFields.length > 0) {
passwordFields[0].value = password;
passwordFields[0].dispatchEvent(new Event('input', { bubbles: true }));
passwordFields[0].dispatchEvent(new Event('change', { bubbles: true }));
}
alert('Credentials autofilled!');
}
// Initialize
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', createUI);
} else {
createUI();
}
})();