znpt-backend/doc/aesDemo.html

459 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AES加密解密工具</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#10b981',
accent: '#6366f1',
dark: '#1e293b',
light: '#f8fafc'
},
fontFamily: {
inter: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.text-shadow {
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.card-shadow {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.transition-custom {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
}
</style>
</head>
<body class="font-inter bg-gradient-to-br from-light to-blue-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-5xl">
<!-- 标题区域 -->
<header class="mb-12 text-center">
<h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-dark mb-3 text-shadow">
<i class="fa-solid fa-lock text-primary mr-3"></i>AES加密解密工具
</h1>
<p class="text-gray-600 text-lg max-w-2xl mx-auto">
使用先进的AES加密算法保护您的数据安全支持多种加密模式和密钥长度
</p>
</header>
<!-- 主内容区 -->
<main class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- 加密区域 -->
<section class="bg-white rounded-2xl p-6 card-shadow transition-custom hover:shadow-xl">
<h2 class="text-2xl font-bold text-dark mb-6 flex items-center">
<i class="fa-solid fa-shield-lock text-primary mr-2"></i>加密
</h2>
<div class="space-y-4">
<div>
<label for="plaintext" class="block text-sm font-medium text-gray-700 mb-1">明文</label>
<textarea id="plaintext" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom resize-none" rows="4" placeholder="请输入要加密的文本..."></textarea>
</div>
<div>
<label for="encrypt-key" class="block text-sm font-medium text-gray-700 mb-1">密钥</label>
<div class="relative">
<input type="text" id="encrypt-key" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom" placeholder="请输入16/24/32字节密钥..." value="1234567890123456">
<button type="button" id="generate-key" class="absolute right-2 top-1/2 -translate-y-1/2 text-primary hover:text-primary/80 transition-custom">
<i class="fa-solid fa-refresh"></i>
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">加密选项</label>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="encrypt-mode" class="block text-xs text-gray-500 mb-1">加密模式</label>
<select id="encrypt-mode" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom">
<option value="ECB">ECB</option>
<option value="CBC">CBC</option>
<option value="CFB">CFB</option>
<option value="OFB">OFB</option>
<option value="CTR">CTR</option>
</select>
</div>
<div>
<label for="encrypt-padding" class="block text-xs text-gray-500 mb-1">填充方式</label>
<select id="encrypt-padding" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom">
<option value="Pkcs7">PKCS#7</option>
<option value="Iso97971">ISO 9797-1</option>
<option value="AnsiX923">ANSI X.923</option>
<option value="Iso10126">ISO 10126</option>
<option value="ZeroPadding">Zero Padding</option>
<option value="NoPadding">No Padding</option>
</select>
</div>
</div>
</div>
<div id="iv-container" class="hidden">
<label for="encrypt-iv" class="block text-sm font-medium text-gray-700 mb-1">初始化向量(IV)</label>
<input type="text" id="encrypt-iv" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom" placeholder="请输入16字节初始化向量...">
</div>
<button id="encrypt-btn" class="w-full bg-primary hover:bg-primary/90 text-white font-medium py-3 px-4 rounded-lg transition-custom transform hover:scale-[1.02] flex items-center justify-center">
<i class="fa-solid fa-lock mr-2"></i>加密
</button>
</div>
</section>
<!-- 解密区域 -->
<section class="bg-white rounded-2xl p-6 card-shadow transition-custom hover:shadow-xl">
<h2 class="text-2xl font-bold text-dark mb-6 flex items-center">
<i class="fa-solid fa-unlock text-secondary mr-2"></i>解密
</h2>
<div class="space-y-4">
<div>
<label for="ciphertext" class="block text-sm font-medium text-gray-700 mb-1">密文</label>
<textarea id="ciphertext" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom resize-none" rows="4" placeholder="请输入要解密的文本..."></textarea>
</div>
<div>
<label for="decrypt-key" class="block text-sm font-medium text-gray-700 mb-1">密钥</label>
<input type="text" id="decrypt-key" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom" placeholder="请输入16/24/32字节密钥..." value="1234567890123456">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">解密选项</label>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="decrypt-mode" class="block text-xs text-gray-500 mb-1">解密模式</label>
<select id="decrypt-mode" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom">
<option value="ECB">ECB</option>
<option value="CBC">CBC</option>
<option value="CFB">CFB</option>
<option value="OFB">OFB</option>
<option value="CTR">CTR</option>
</select>
</div>
<div>
<label for="decrypt-padding" class="block text-xs text-gray-500 mb-1">填充方式</label>
<select id="decrypt-padding" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom">
<option value="Pkcs7">PKCS#7</option>
<option value="Iso97971">ISO 9797-1</option>
<option value="AnsiX923">ANSI X.923</option>
<option value="Iso10126">ISO 10126</option>
<option value="ZeroPadding">Zero Padding</option>
<option value="NoPadding">No Padding</option>
</select>
</div>
</div>
</div>
<div id="decrypt-iv-container" class="hidden">
<label for="decrypt-iv" class="block text-sm font-medium text-gray-700 mb-1">初始化向量(IV)</label>
<input type="text" id="decrypt-iv" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom" placeholder="请输入16字节初始化向量...">
</div>
<button id="decrypt-btn" class="w-full bg-secondary hover:bg-secondary/90 text-white font-medium py-3 px-4 rounded-lg transition-custom transform hover:scale-[1.02] flex items-center justify-center">
<i class="fa-solid fa-unlock mr-2"></i>解密
</button>
</div>
</section>
</main>
<!-- 结果展示区 -->
<section class="mt-8 bg-white rounded-2xl p-6 card-shadow">
<h2 class="text-2xl font-bold text-dark mb-4 flex items-center">
<i class="fa-solid fa-file-text text-accent mr-2"></i>结果
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">加密结果</label>
<div class="relative">
<textarea id="encrypt-result" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-accent/50 focus:border-accent transition-custom resize-none" rows="4" readonly placeholder="加密结果将显示在这里..."></textarea>
<button id="copy-encrypt" class="absolute right-2 top-2 text-gray-500 hover:text-accent transition-custom">
<i class="fa-solid fa-copy"></i>
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">解密结果</label>
<div class="relative">
<textarea id="decrypt-result" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-accent/50 focus:border-accent transition-custom resize-none" rows="4" readonly placeholder="解密结果将显示在这里..."></textarea>
<button id="copy-decrypt" class="absolute right-2 top-2 text-gray-500 hover:text-accent transition-custom">
<i class="fa-solid fa-copy"></i>
</button>
</div>
</div>
</div>
</section>
<!-- 信息提示区 -->
<div id="notification" class="fixed bottom-4 right-4 bg-dark text-white px-6 py-3 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center">
<i id="notification-icon" class="fa-solid fa-info-circle mr-2"></i>
<span id="notification-message">操作成功</span>
</div>
</div>
<script>
// 加密函数
function encrypt() {
const plaintext = document.getElementById('plaintext').value.trim();
const key = document.getElementById('encrypt-key').value.trim();
const mode = document.getElementById('encrypt-mode').value;
const padding = document.getElementById('encrypt-padding').value;
const iv = document.getElementById('encrypt-iv').value.trim();
if (!plaintext) {
showNotification('请输入明文', 'error');
return;
}
if (!key) {
showNotification('请输入密钥', 'error');
return;
}
try {
// 获取加密模式
const modeObj = getModeObject(mode);
// 获取填充方式
const paddingObj = getPaddingObject(padding);
// 准备加密参数
const keyUtf8 = CryptoJS.enc.Utf8.parse(key);
let encrypted;
// 根据模式是否需要IV
if (mode === 'ECB') {
encrypted = CryptoJS.AES.encrypt(plaintext, keyUtf8, {
mode: modeObj,
padding: paddingObj
});
} else {
if (!iv) {
showNotification('使用该模式需要输入初始化向量(IV)', 'error');
return;
}
const ivUtf8 = CryptoJS.enc.Utf8.parse(iv);
encrypted = CryptoJS.AES.encrypt(plaintext, keyUtf8, {
iv: ivUtf8,
mode: modeObj,
padding: paddingObj
});
}
// 显示加密结果
const encryptedResult = encrypted.toString();
document.getElementById('encrypt-result').value = encryptedResult;
document.getElementById('ciphertext').value = encryptedResult;
showNotification('加密成功', 'success');
} catch (error) {
console.error('加密错误:', error);
showNotification('加密失败: ' + error.message, 'error');
}
}
// 解密函数
function decrypt() {
const ciphertext = document.getElementById('ciphertext').value.trim();
const key = document.getElementById('decrypt-key').value.trim();
const mode = document.getElementById('decrypt-mode').value;
const padding = document.getElementById('decrypt-padding').value;
const iv = document.getElementById('decrypt-iv').value.trim();
if (!ciphertext) {
showNotification('请输入密文', 'error');
return;
}
if (!key) {
showNotification('请输入密钥', 'error');
return;
}
try {
// 获取解密模式
const modeObj = getModeObject(mode);
// 获取填充方式
const paddingObj = getPaddingObject(padding);
// 准备解密参数
const keyUtf8 = CryptoJS.enc.Utf8.parse(key);
// 根据模式是否需要IV
let decrypted;
if (mode === 'ECB') {
decrypted = CryptoJS.AES.decrypt(ciphertext, keyUtf8, {
mode: modeObj,
padding: paddingObj
});
} else {
if (!iv) {
showNotification('使用该模式需要输入初始化向量(IV)', 'error');
return;
}
const ivUtf8 = CryptoJS.enc.Utf8.parse(iv);
decrypted = CryptoJS.AES.decrypt(ciphertext, keyUtf8, {
iv: ivUtf8,
mode: modeObj,
padding: paddingObj
});
}
// 显示解密结果
const decryptedResult = decrypted.toString(CryptoJS.enc.Utf8);
document.getElementById('decrypt-result').value = decryptedResult;
showNotification('解密成功', 'success');
} catch (error) {
console.error('解密错误:', error);
showNotification('解密失败: ' + error.message, 'error');
}
}
// 根据名称获取加密/解密模式对象
function getModeObject(modeName) {
switch (modeName) {
case 'ECB': return CryptoJS.mode.ECB;
case 'CBC': return CryptoJS.mode.CBC;
case 'CFB': return CryptoJS.mode.CFB;
case 'OFB': return CryptoJS.mode.OFB;
case 'CTR': return CryptoJS.mode.CTR;
default: return CryptoJS.mode.ECB;
}
}
// 根据名称获取填充方式对象
function getPaddingObject(paddingName) {
switch (paddingName) {
case 'Pkcs7': return CryptoJS.pad.Pkcs7;
case 'Iso97971': return CryptoJS.pad.Iso97971;
case 'AnsiX923': return CryptoJS.pad.AnsiX923;
case 'Iso10126': return CryptoJS.pad.Iso10126;
case 'ZeroPadding': return CryptoJS.pad.ZeroPadding;
case 'NoPadding': return CryptoJS.pad.NoPadding;
default: return CryptoJS.pad.Pkcs7;
}
}
// 生成随机密钥
function generateRandomKey(length = 16) {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let key = "";
for (let i = 0; i < length; i++) {
key += charset.charAt(Math.floor(Math.random() * charset.length));
}
return key;
}
// 显示通知
function showNotification(message, type = 'info') {
const notification = document.getElementById('notification');
const notificationIcon = document.getElementById('notification-icon');
const notificationMessage = document.getElementById('notification-message');
// 设置通知类型
notification.className = 'fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center';
if (type === 'success') {
notification.classList.add('bg-green-500', 'text-white');
notificationIcon.className = 'fa-solid fa-check-circle mr-2';
} else if (type === 'error') {
notification.classList.add('bg-red-500', 'text-white');
notificationIcon.className = 'fa-solid fa-exclamation-circle mr-2';
} else {
notification.classList.add('bg-dark', 'text-white');
notificationIcon.className = 'fa-solid fa-info-circle mr-2';
}
// 设置通知消息
notificationMessage.textContent = message;
// 显示通知
setTimeout(() => {
notification.classList.remove('translate-y-20', 'opacity-0');
}, 10);
// 3秒后隐藏通知
setTimeout(() => {
notification.classList.add('translate-y-20', 'opacity-0');
}, 3000);
}
// 复制到剪贴板
function copyToClipboard(elementId) {
const element = document.getElementById(elementId);
element.select();
document.execCommand('copy');
showNotification('已复制到剪贴板', 'success');
}
// 模式变更事件处理
function handleModeChange() {
const encryptMode = document.getElementById('encrypt-mode').value;
const decryptMode = document.getElementById('decrypt-mode').value;
// 显示或隐藏加密IV输入框
const encryptIvContainer = document.getElementById('iv-container');
if (encryptMode === 'ECB') {
encryptIvContainer.classList.add('hidden');
} else {
encryptIvContainer.classList.remove('hidden');
}
// 显示或隐藏解密IV输入框
const decryptIvContainer = document.getElementById('decrypt-iv-container');
if (decryptMode === 'ECB') {
decryptIvContainer.classList.add('hidden');
} else {
decryptIvContainer.classList.remove('hidden');
}
}
// 生成随机密钥
document.getElementById('generate-key').addEventListener('click', () => {
document.getElementById('encrypt-key').value = generateRandomKey(16);
document.getElementById('decrypt-key').value = document.getElementById('encrypt-key').value;
showNotification('已生成随机密钥', 'success');
});
// 加密按钮点击事件
document.getElementById('encrypt-btn').addEventListener('click', encrypt);
// 解密按钮点击事件
document.getElementById('decrypt-btn').addEventListener('click', decrypt);
// 复制加密结果
document.getElementById('copy-encrypt').addEventListener('click', () => copyToClipboard('encrypt-result'));
// 复制解密结果
document.getElementById('copy-decrypt').addEventListener('click', () => copyToClipboard('decrypt-result'));
// 模式变更事件
document.getElementById('encrypt-mode').addEventListener('change', handleModeChange);
document.getElementById('decrypt-mode').addEventListener('change', handleModeChange);
// 初始化
handleModeChange();
// 添加示例数据
document.getElementById('plaintext').value = '这是一个使用AES加密的示例文本您可以替换为自己的内容。';
</script>
</body>
</html>