HTML+CSS+JavaScript实现的AES加密工具网页应用,包含完整的UI界面和加密/解密功能

荻酷分享:以下是基于HTML+CSS+JavaScript实现的AES加密工具网页应用,包含完整的UI界面和加密/解密功能:

JS加密工具

完整功能:实现AES-256加密/解密功能,包含盐值和IV生成增强安全性

现代化UI:采用渐变色背景、毛玻璃效果卡片和流畅动画

响应式设计:适配不同屏幕尺寸,移动端友好

完整交互:包含密钥显示切换、结果复制、本地保存等功能

安全提示:所有操作在本地完成,不传输数据到服务器

错误处理:完善的错误捕获和用户提示机制

演示效果:

index.html代码如下:

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JS加密工具</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
    <style>
        .gradient-bg {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        .card-hover {
            transition: all 0.3s ease;
        }
        .card-hover:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .fade-in {
            animation: fadeIn 0.5s ease-in;
        }
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
    </style>
</head>
<body class="min-h-screen gradient-bg text-gray-100">
    <div class="container mx-auto px-4 py-12">
        <header class="text-center mb-12">
            <h1 class="text-4xl font-bold mb-2">JS加密工具</h1>
            <p class="text-xl opacity-90">基于AES算法的安全加密/解密工具</p>
        </header>

        <main class="max-w-4xl mx-auto">
            <div class="bg-white bg-opacity-10 backdrop-filter backdrop-blur-lg rounded-xl shadow-xl overflow-hidden card-hover">
                <div class="p-6">
                    <div class="flex flex-col md:flex-row gap-6">
                        <div class="flex-1">
                            <div class="mb-6">
                                <label class="block text-sm font-medium mb-2" for="inputText">输入文本</label>
                                <textarea id="inputText" rows="6" class="w-full px-4 py-3 rounded-lg bg-white bg-opacity-20 border border-white border-opacity-30 focus:outline-none focus:ring-2 focus:ring-purple-300 focus:border-transparent placeholder-gray-300" placeholder="请输入要加密/解密的文本..."></textarea>
                            </div>

                            <div class="mb-6">
                                <label class="block text-sm font-medium mb-2" for="secretKey">密钥</label>
                                <div class="relative">
                                    <input type="password" id="secretKey" class="w-full px-4 py-3 rounded-lg bg-white bg-opacity-20 border border-white border-opacity-30 focus:outline-none focus:ring-2 focus:ring-purple-300 focus:border-transparent placeholder-gray-300" placeholder="请输入加密密钥">
                                    <button id="toggleKey" class="absolute right-3 top-3 text-gray-300 hover:text-white">
                                        <i class="far fa-eye"></i>
                                    </button>
                                </div>
                            </div>

                            <div class="flex flex-wrap gap-4 mb-6">
                                <button id="encryptBtn" class="flex-1 bg-purple-600 hover:bg-purple-700 text-white font-medium py-3 px-6 rounded-lg transition duration-300 flex items-center justify-center gap-2">
                                    <i class="fas fa-lock"></i> 加密
                                </button>
                                <button id="decryptBtn" class="flex-1 bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-6 rounded-lg transition duration-300 flex items-center justify-center gap-2">
                                    <i class="fas fa-unlock"></i> 解密
                                </button>
                                <button id="clearBtn" class="flex-1 bg-gray-600 hover:bg-gray-700 text-white font-medium py-3 px-6 rounded-lg transition duration-300 flex items-center justify-center gap-2">
                                    <i class="fas fa-trash-alt"></i> 清空
                                </button>
                            </div>
                        </div>

                        <div class="flex-1">
                            <label class="block text-sm font-medium mb-2" for="outputText">结果</label>
                            <textarea id="outputText" rows="6" readonly class="w-full px-4 py-3 rounded-lg bg-white bg-opacity-20 border border-white border-opacity-30 focus:outline-none focus:ring-2 focus:ring-purple-300 focus:border-transparent placeholder-gray-300" placeholder="加密/解密结果将显示在这里..."></textarea>
                            
                            <div class="mt-4 flex gap-4">
                                <button id="copyBtn" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-300 flex items-center justify-center gap-2">
                                    <i class="far fa-copy"></i> 复制结果
                                </button>
                                <button id="saveBtn" class="flex-1 bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition duration-300 flex items-center justify-center gap-2">
                                    <i class="far fa-save"></i> 保存到本地
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="mt-8 bg-white bg-opacity-10 backdrop-filter backdrop-blur-lg rounded-xl shadow-xl overflow-hidden card-hover fade-in">
                <div class="p-6">
                    <h2 class="text-xl font-semibold mb-4">使用说明</h2>
                    <ul class="space-y-2 text-sm opacity-90">
                        <li><i class="fas fa-info-circle mr-2"></i> 使用AES-256算法进行加密/解密</li>
                        <li><i class="fas fa-key mr-2"></i> 密钥长度建议至少16个字符</li>
                        <li><i class="fas fa-shield-alt mr-2"></i> 所有操作均在浏览器本地完成,数据不会上传到服务器</li>
                        <li><i class="fas fa-history mr-2"></i> 加密结果包含随机盐值,每次加密结果不同但都能解密</li>
                        <li><i class="fas fa-exclamation-triangle mr-2"></i> 请妥善保管密钥,丢失后将无法解密数据</li>
                    </ul>
                </div>
            </div>
        </main>

        <footer class="mt-16 text-center text-sm opacity-75">
            <p>© 2025 JS加密工具 | 基于CryptoJS实现</p>
        </footer>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 切换密钥可见性
            const toggleKey = document.getElementById('toggleKey');
            const secretKey = document.getElementById('secretKey');
            toggleKey.addEventListener('click', function() {
                if (secretKey.type === 'password') {
                    secretKey.type = 'text';
                    toggleKey.innerHTML = '<i class="far fa-eye-slash"></i>';
                } else {
                    secretKey.type = 'password';
                    toggleKey.innerHTML = '<i class="far fa-eye"></i>';
                }
            });

            // 加密函数
            function encrypt(text, key) {
                if (!text || !key) {
                    alert('请输入文本和密钥');
                    return null;
                }
                
                try {
                    const salt = CryptoJS.lib.WordArray.random(128/8);
                    const iv = CryptoJS.lib.WordArray.random(128/8);
                    const key256Bits = CryptoJS.PBKDF2(key, salt, {
                        keySize: 256/32,
                        iterations: 1000
                    });
                    
                    const encrypted = CryptoJS.AES.encrypt(text, key256Bits, { 
                        iv: iv,
                        padding: CryptoJS.pad.Pkcs7,
                        mode: CryptoJS.mode.CBC
                    });
                    
                    // 组合盐值、IV和加密数据
                    const result = {
                        salt: salt.toString(),
                        iv: iv.toString(),
                        ciphertext: encrypted.toString()
                    };
                    
                    return JSON.stringify(result);
                } catch (error) {
                    console.error('加密错误:', error);
                    alert('加密过程中发生错误');
                    return null;
                }
            }

            // 解密函数
            function decrypt(encryptedData, key) {
                if (!encryptedData || !key) {
                    alert('请输入加密数据和密钥');
                    return null;
                }
                
                try {
                    const data = JSON.parse(encryptedData);
                    const salt = CryptoJS.enc.Hex.parse(data.salt);
                    const iv = CryptoJS.enc.Hex.parse(data.iv);
                    
                    const key256Bits = CryptoJS.PBKDF2(key, salt, {
                        keySize: 256/32,
                        iterations: 1000
                    });
                    
                    const decrypted = CryptoJS.AES.decrypt(data.ciphertext, key256Bits, { 
                        iv: iv,
                        padding: CryptoJS.pad.Pkcs7,
                        mode: CryptoJS.mode.CBC
                    });
                    
                    return decrypted.toString(CryptoJS.enc.Utf8);
                } catch (error) {
                    console.error('解密错误:', error);
                    alert('解密失败,请检查密钥或数据是否正确');
                    return null;
                }
            }

            // 按钮事件绑定
            document.getElementById('encryptBtn').addEventListener('click', function() {
                const inputText = document.getElementById('inputText').value;
                const key = document.getElementById('secretKey').value;
                const encrypted = encrypt(inputText, key);
                if (encrypted) {
                    document.getElementById('outputText').value = encrypted;
                }
            });

            document.getElementById('decryptBtn').addEventListener('click', function() {
                const inputText = document.getElementById('inputText').value;
                const key = document.getElementById('secretKey').value;
                const decrypted = decrypt(inputText, key);
                if (decrypted) {
                    document.getElementById('outputText').value = decrypted;
                }
            });

            document.getElementById('clearBtn').addEventListener('click', function() {
                document.getElementById('inputText').value = '';
                document.getElementById('outputText').value = '';
                document.getElementById('secretKey').value = '';
            });

            document.getElementById('copyBtn').addEventListener('click', function() {
                const outputText = document.getElementById('outputText');
                outputText.select();
                document.execCommand('copy');
                
                // 显示复制成功提示
                const originalText = this.innerHTML;
                this.innerHTML = '<i class="fas fa-check"></i> 已复制';
                setTimeout(() => {
                    this.innerHTML = originalText;
                }, 2000);
            });

            document.getElementById('saveBtn').addEventListener('click', function() {
                const outputText = document.getElementById('outputText').value;
                if (!outputText) {
                    alert('没有可保存的内容');
                    return;
                }
                
                const blob = new Blob([outputText], { type: 'text/plain' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = 'encrypted_data.txt';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
                
                // 显示保存成功提示
                const originalText = this.innerHTML;
                this.innerHTML = '<i class="fas fa-check"></i> 已保存';
                setTimeout(() => {
                    this.innerHTML = originalText;
                }, 2000);
            });
        });
    </script>
</body>
</html>
相关推荐
EndingCoder1 小时前
React 19 与 Next.js:利用最新 React 功能
前端·javascript·后端·react.js·前端框架·全栈·next.js
ITMan彪叔1 小时前
Nodejs打包 Webpack 中 __dirname 的正确配置与行为解析
javascript·后端
风中凌乱的L1 小时前
vue 一键打包上传
前端·javascript·vue.js
张元清1 小时前
useMergedRefs: 组件封装必不可少的自定义Hook
前端·javascript·面试
openInula前端开源社区1 小时前
【openInula茶话会】第四期:openInula API2.0编译器原理
前端·javascript
sorryhc2 小时前
【AI解读源码系列】ant design mobile——CapsuleTabs胶囊选项卡
前端·javascript·react.js
巧克力792 小时前
js数组去重的方法
javascript·面试
Sheeep2 小时前
Cursor 的使用之学会使用 cursor rule
javascript·后端
本末倒置1833 小时前
Svelte邪修的JSDoc,到底是个啥?
前端·javascript·面试
李明卫杭州3 小时前
CSS中的background-clip详解
前端·javascript