This commit is contained in:
陶然
2026-03-02 15:52:59 +08:00
parent 5187935888
commit 68b493c725
4 changed files with 2 additions and 786 deletions
-339
View File
@@ -1,339 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import ToolDetail from '@/components/Layout/ToolDetail/ToolDetail.vue'
import { ElMessage } from 'element-plus'
import { copy } from '@/utils/string'
const title = "AES加解密"
// 状态管理
const activeTab = ref('encrypt')
const inputText = ref('')
const outputText = ref('')
const key = ref('')
const iv = ref('')
const mode = ref('CBC')
const keySize = ref(128)
// 加密模式选项
const modeOptions = [
{ label: 'CBC', value: 'CBC' },
{ label: 'ECB', value: 'ECB' }
]
// 密钥长度选项
const keySizeOptions = [
{ label: '128位', value: 128 },
{ label: '192位', value: 192 },
{ label: '256位', value: 256 }
]
// 加密处理
const encrypt = async () => {
if (!inputText.value) {
ElMessage.warning('请输入要加密的文本')
return
}
if (!key.value) {
ElMessage.warning('请输入密钥')
return
}
if (mode.value === 'CBC' && !iv.value) {
ElMessage.warning('CBC模式需要输入初始化向量(IV)')
return
}
try {
// 生成密钥
const cryptoKey = await generateKey(key.value, keySize.value)
// 加密
const encrypted = await aesEncrypt(inputText.value, cryptoKey, iv.value, mode.value)
outputText.value = btoa(encrypted)
ElMessage.success('加密成功')
} catch (error) {
ElMessage.error('加密失败:' + error)
}
}
// 解密处理
const decrypt = async () => {
if (!inputText.value) {
ElMessage.warning('请输入要解密的文本')
return
}
if (!key.value) {
ElMessage.warning('请输入密钥')
return
}
if (mode.value === 'CBC' && !iv.value) {
ElMessage.warning('CBC模式需要输入初始化向量(IV)')
return
}
try {
// 生成密钥
const cryptoKey = await generateKey(key.value, keySize.value)
// 解密
const decrypted = await aesDecrypt(atob(inputText.value), cryptoKey, iv.value, mode.value)
outputText.value = decrypted
ElMessage.success('解密成功')
} catch (error) {
ElMessage.error('解密失败:' + error)
}
}
// 生成密钥
const generateKey = async (keyStr: string, size: number) => {
// 使用SHA-256哈希密钥,确保长度正确
const encoder = new TextEncoder()
const keyData = encoder.encode(keyStr)
const hashBuffer = await crypto.subtle.digest('SHA-256', keyData)
const hashArray = Array.from(new Uint8Array(hashBuffer))
// 根据密钥长度截取
const keyBytes = size / 8
const keyBuffer = new Uint8Array(hashArray.slice(0, keyBytes))
return await crypto.subtle.importKey(
'raw',
keyBuffer,
{ name: 'AES-' + mode.value },
false,
['encrypt', 'decrypt']
)
}
// AES加密
const aesEncrypt = async (text: string, key: CryptoKey, ivStr: string, mode: string) => {
const encoder = new TextEncoder()
const data = encoder.encode(text)
let ivBuffer: Uint8Array
if (mode === 'CBC') {
// 使用SHA-256哈希IV,确保长度为16字节
const ivData = encoder.encode(ivStr)
const ivHashBuffer = await crypto.subtle.digest('SHA-256', ivData)
ivBuffer = new Uint8Array(ivHashBuffer.slice(0, 16))
}
const algorithm: AlgorithmIdentifier = mode === 'CBC'
? { name: 'AES-CBC', iv: ivBuffer! } as AesCbcParams
: { name: 'AES-ECB' }
const encrypted = await crypto.subtle.encrypt(algorithm, key, data)
return String.fromCharCode(...new Uint8Array(encrypted))
}
// AES解密
const aesDecrypt = async (text: string, key: CryptoKey, ivStr: string, mode: string) => {
const data = new Uint8Array(text.split('').map(char => char.charCodeAt(0)))
let ivBuffer: Uint8Array
if (mode === 'CBC') {
// 使用SHA-256哈希IV,确保长度为16字节
const encoder = new TextEncoder()
const ivData = encoder.encode(ivStr)
const ivHashBuffer = await crypto.subtle.digest('SHA-256', ivData)
ivBuffer = new Uint8Array(ivHashBuffer.slice(0, 16))
}
const algorithm: AlgorithmIdentifier = mode === 'CBC'
? { name: 'AES-CBC', iv: ivBuffer! } as AesCbcParams
: { name: 'AES-ECB' }
const decrypted = await crypto.subtle.decrypt(algorithm, key, data)
const decoder = new TextDecoder()
return decoder.decode(decrypted)
}
// 复制结果
const copyResult = () => {
if (!outputText.value) {
ElMessage.warning('没有可复制的内容')
return
}
copy(outputText.value)
}
// 清空输入
const clearInput = () => {
inputText.value = ''
outputText.value = ''
}
</script>
<template>
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="title"></DetailHeader>
<div class="p-4 rounded-2xl bg-white">
<el-tabs v-model="activeTab">
<el-tab-pane label="加密" name="encrypt">
<!-- 输入部分 -->
<div class="mb-4">
<el-input
v-model="inputText"
type="textarea"
:rows="4"
placeholder="请输入要加密的文本"
class="mb-2"
/>
<el-input
v-model="key"
placeholder="请输入密钥"
class="mb-2"
/>
<el-input
v-model="iv"
placeholder="请输入初始化向量(IV) (CBC模式必填)"
class="mb-2"
/>
<div class="flex gap-4 items-center mb-2">
<div class="flex items-center gap-2">
<el-text>加密模式</el-text>
<el-select v-model="mode" style="width: 120px;">
<el-option
v-for="option in modeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</div>
<div class="flex items-center gap-2">
<el-text>密钥长度</el-text>
<el-select v-model="keySize" style="width: 120px;">
<el-option
v-for="option in keySizeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="mb-4">
<el-button type="primary" @click="encrypt">加密</el-button>
<el-button @click="clearInput">清空</el-button>
</div>
<!-- 结果部分 -->
<div>
<el-input
v-model="outputText"
type="textarea"
:rows="4"
placeholder="加密结果"
readonly
>
<template #append>
<el-button @click="copyResult">复制</el-button>
</template>
</el-input>
</div>
</el-tab-pane>
<el-tab-pane label="解密" name="decrypt">
<!-- 输入部分 -->
<div class="mb-4">
<el-input
v-model="inputText"
type="textarea"
:rows="4"
placeholder="请输入要解密的文本"
class="mb-2"
/>
<el-input
v-model="key"
placeholder="请输入密钥"
class="mb-2"
/>
<el-input
v-model="iv"
placeholder="请输入初始化向量(IV) (CBC模式必填)"
class="mb-2"
/>
<div class="flex gap-4 items-center mb-2">
<div class="flex items-center gap-2">
<el-text>加密模式</el-text>
<el-select v-model="mode" class="w-32">
<el-option
v-for="option in modeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</div>
<div class="flex items-center gap-2">
<el-text>密钥长度</el-text>
<el-select v-model="keySize" class="w-32">
<el-option
v-for="option in keySizeOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="mb-4">
<el-button type="primary" @click="decrypt">解密</el-button>
<el-button @click="clearInput">清空</el-button>
</div>
<!-- 结果部分 -->
<div>
<el-input
v-model="outputText"
type="textarea"
:rows="4"
placeholder="解密结果"
readonly
>
<template #append>
<el-button @click="copyResult">复制</el-button>
</template>
</el-input>
</div>
</el-tab-pane>
</el-tabs>
</div>
<!-- desc -->
<ToolDetail title="描述">
<el-text>
在线AES加解密工具支持CBC和ECB模式支持128位192256位密钥长度可用于数据加密和解密
</el-text>
</ToolDetail>
</div>
</template>
<style scoped>
</style>
@@ -1,419 +0,0 @@
<template>
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="title"></DetailHeader>
<div class="p-4 rounded-2xl bg-white">
<div class="tool-content">
<div class="input-section">
<el-tabs v-model="activeTab">
<el-tab-pane label="加密" name="encrypt">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<el-form label-width="120px">
<el-form-item label="输入内容">
<el-input
v-model="encryptInput"
type="textarea"
:rows="6"
placeholder="请输入待加密的明文"
/>
</el-form-item>
<el-form-item label="密钥">
<el-input
v-model="encryptKey"
type="password"
placeholder="请输入密钥"
/>
</el-form-item>
<el-form-item label="加密模式">
<el-select v-model="encryptMode" placeholder="请选择加密模式">
<el-option label="CBC" value="cbc" />
<el-option label="ECB" value="ecb" />
<el-option label="CFB" value="cfb" />
<el-option label="CTR" value="ctr" />
<el-option label="OFB" value="ofb" />
</el-select>
</el-form-item>
<el-form-item label="填充方式">
<el-select v-model="encryptPadding" placeholder="请选择填充方式">
<el-option label="Pkcs7" value="pkcs7" />
<el-option label="Iso97971" value="iso97971" />
<el-option label="AnsiX923" value="ansix923" />
<el-option label="ZeroPadding" value="zeropadding" />
<el-option label="NoPadding" value="nopadding" />
</el-select>
</el-form-item>
<el-form-item label="初始向量 (IV)" v-if="encryptMode !== 'ecb'">
<el-input
v-model="encryptIv"
placeholder="请输入16位初始向量"
/>
</el-form-item>
<el-form-item label="输出编码">
<el-select v-model="encryptOutputEncoding" placeholder="请选择输出编码">
<el-option label="Base64" value="base64" />
<el-option label="HEX" value="hex" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="encrypt">加密</el-button>
<el-button @click="clearEncrypt">清空</el-button>
</el-form-item>
</el-form>
</div>
<div>
<el-form label-width="120px">
<el-form-item label="加密结果">
<el-input
v-model="encryptOutput"
type="textarea"
:rows="10"
placeholder="加密后的密文将显示在这里"
/>
</el-form-item>
<el-form-item>
<el-button @click="copyEncryptResult">复制结果</el-button>
</el-form-item>
</el-form>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="解密" name="decrypt">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<el-form label-width="120px">
<el-form-item label="输入内容">
<el-input
v-model="decryptInput"
type="textarea"
:rows="6"
placeholder="请输入待解密的密文"
/>
</el-form-item>
<el-form-item label="密钥">
<el-input
v-model="decryptKey"
type="password"
placeholder="请输入密钥"
/>
</el-form-item>
<el-form-item label="解密模式">
<el-select v-model="decryptMode" placeholder="请选择解密模式">
<el-option label="CBC" value="cbc" />
<el-option label="ECB" value="ecb" />
<el-option label="CFB" value="cfb" />
<el-option label="CTR" value="ctr" />
<el-option label="OFB" value="ofb" />
</el-select>
</el-form-item>
<el-form-item label="填充方式">
<el-select v-model="decryptPadding" placeholder="请选择填充方式">
<el-option label="Pkcs7" value="pkcs7" />
<el-option label="Iso97971" value="iso97971" />
<el-option label="AnsiX923" value="ansix923" />
<el-option label="ZeroPadding" value="zeropadding" />
<el-option label="NoPadding" value="nopadding" />
</el-select>
</el-form-item>
<el-form-item label="初始向量 (IV)" v-if="decryptMode !== 'ecb'">
<el-input
v-model="decryptIv"
placeholder="请输入16位初始向量"
/>
</el-form-item>
<el-form-item label="输入编码">
<el-select v-model="decryptInputEncoding" placeholder="请选择输入编码">
<el-option label="Base64" value="base64" />
<el-option label="HEX" value="hex" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="decrypt">解密</el-button>
<el-button @click="clearDecrypt">清空</el-button>
</el-form-item>
</el-form>
</div>
<div>
<el-form label-width="120px">
<el-form-item label="解密结果">
<el-input
v-model="decryptOutput"
type="textarea"
:rows="10"
placeholder="解密后的明文将显示在这里"
/>
</el-form-item>
<el-form-item>
<el-button @click="copyDecryptResult">复制结果</el-button>
</el-form-item>
</el-form>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
<!-- desc -->
<ToolDetail title="描述">
<el-text>
在线AES加密解密工具支持多种加密模式和填充方式提供安全可靠的数据加密解密服务
</el-text>
</ToolDetail>
<!-- 安全使用建议 -->
<ToolDetail title="安全使用建议">
<el-text>
<ul>
<li>使用强随机数生成器生成密钥和IV</li>
<li>推荐使用CBC模式而非ECB模式</li>
<li>定期更换密钥和IV</li>
<li>妥善保管密钥不要泄露给他人</li>
<li>在生产环境中使用AES-256而非AES-128</li>
</ul>
</el-text>
</ToolDetail>
<!-- 常见应用场景 -->
<ToolDetail title="常见应用场景">
<el-text>
<ul>
<li>数据传输加密保护网络传输中的敏感数据</li>
<li>文件存储加密加密本地存储的重要文件</li>
<li>API通信加密保护API接口的数据安全</li>
</ul>
</el-text>
</ToolDetail>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import ToolDetail from '@/components/Layout/ToolDetail/ToolDetail.vue'
import CryptoJS from 'crypto-js';
const title = "AES加密解密"
const activeTab = ref('encrypt');
// 加密相关
const encryptInput = ref('');
const encryptKey = ref('');
const encryptMode = ref('cbc');
const encryptPadding = ref('pkcs7');
const encryptIv = ref('');
const encryptOutputEncoding = ref('base64');
const encryptOutput = ref('');
// 解密相关
const decryptInput = ref('');
const decryptKey = ref('');
const decryptMode = ref('cbc');
const decryptPadding = ref('pkcs7');
const decryptIv = ref('');
const decryptInputEncoding = ref('base64');
const decryptOutput = ref('');
// 获取加密模式
const getCipherMode = (mode: string) => {
switch (mode) {
case 'cbc':
return CryptoJS.mode.CBC;
case 'ecb':
return CryptoJS.mode.ECB;
case 'cfb':
return CryptoJS.mode.CFB;
case 'ctr':
return CryptoJS.mode.CTR;
case 'ofb':
return CryptoJS.mode.OFB;
default:
return CryptoJS.mode.CBC;
}
};
// 获取填充方式
const getPadding = (padding: string) => {
switch (padding) {
case 'pkcs7':
return CryptoJS.pad.Pkcs7;
case 'iso97971':
return CryptoJS.pad.Iso97971;
case 'ansix923':
return CryptoJS.pad.AnsiX923;
case 'zeropadding':
return CryptoJS.pad.ZeroPadding;
case 'nopadding':
return CryptoJS.pad.NoPadding;
default:
return CryptoJS.pad.Pkcs7;
}
};
// 加密函数
const encrypt = () => {
if (!encryptInput.value) {
ElMessage.warning('请输入待加密的明文');
return;
}
if (!encryptKey.value) {
ElMessage.warning('请输入密钥');
return;
}
if (encryptMode.value !== 'ecb' && !encryptIv.value) {
ElMessage.warning('请输入初始向量 (IV)');
return;
}
try {
const key = CryptoJS.enc.Utf8.parse(encryptKey.value);
const iv = encryptMode.value !== 'ecb' ? CryptoJS.enc.Utf8.parse(encryptIv.value) : undefined;
const mode = getCipherMode(encryptMode.value);
const padding = getPadding(encryptPadding.value);
const cipher = CryptoJS.AES.encrypt(encryptInput.value, key, {
iv: iv,
mode: mode,
padding: padding
});
if (encryptOutputEncoding.value === 'base64') {
encryptOutput.value = cipher.toString();
} else {
encryptOutput.value = cipher.ciphertext.toString(CryptoJS.enc.Hex);
}
ElMessage.success('加密成功');
} catch (error) {
ElMessage.error('加密失败:' + (error as Error).message);
}
};
// 解密函数
const decrypt = () => {
if (!decryptInput.value) {
ElMessage.warning('请输入待解密的密文');
return;
}
if (!decryptKey.value) {
ElMessage.warning('请输入密钥');
return;
}
if (decryptMode.value !== 'ecb' && !decryptIv.value) {
ElMessage.warning('请输入初始向量 (IV)');
return;
}
try {
const key = CryptoJS.enc.Utf8.parse(decryptKey.value);
const iv = decryptMode.value !== 'ecb' ? CryptoJS.enc.Utf8.parse(decryptIv.value) : undefined;
const mode = getCipherMode(decryptMode.value);
const padding = getPadding(decryptPadding.value);
let ciphertext;
if (decryptInputEncoding.value === 'base64') {
ciphertext = decryptInput.value;
} else {
ciphertext = CryptoJS.enc.Hex.parse(decryptInput.value);
}
const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {
iv: iv,
mode: mode,
padding: padding
});
decryptOutput.value = decrypted.toString(CryptoJS.enc.Utf8);
ElMessage.success('解密成功');
} catch (error) {
ElMessage.error('解密失败:' + (error as Error).message);
}
};
// 清空加密
const clearEncrypt = () => {
encryptInput.value = '';
encryptKey.value = '';
encryptIv.value = '';
encryptOutput.value = '';
};
// 清空解密
const clearDecrypt = () => {
decryptInput.value = '';
decryptKey.value = '';
decryptIv.value = '';
decryptOutput.value = '';
};
// 复制加密结果
const copyEncryptResult = () => {
if (!encryptOutput.value) {
ElMessage.warning('没有可复制的内容');
return;
}
navigator.clipboard.writeText(encryptOutput.value).then(() => {
ElMessage.success('已复制加密结果');
}).catch(() => {
ElMessage.error('复制失败');
});
};
// 复制解密结果
const copyDecryptResult = () => {
if (!decryptOutput.value) {
ElMessage.warning('没有可复制的内容');
return;
}
navigator.clipboard.writeText(decryptOutput.value).then(() => {
ElMessage.success('已复制解密结果');
}).catch(() => {
ElMessage.error('复制失败');
});
};
</script>
<style scoped>
.tool-content {
display: flex;
flex-direction: column;
gap: 20px;
}
.input-section {
width: 100%;
}
@media (max-width: 768px) {
.grid-cols-1.md\:grid-cols-2 {
grid-template-columns: 1fr;
}
}
</style>
+1 -18
View File
@@ -161,15 +161,7 @@ export function getToolsCate() {
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'AES加解密',
logo: '/images/logo/md5.png',
desc: '在线AES加解密工具,支持多种加密模式和填充方式,提供安全可靠的数据加密解密服务',
url: '/aes/',
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'Hash计算器',
@@ -179,15 +171,6 @@ export function getToolsCate() {
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'SHA1加解密',
logo: '/images/logo/sha1.svg',
desc: '在线SHA1哈希计算器,用于计算文本的SHA1哈希值',
url: '/sha1/',
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'XML格式化',
+1 -10
View File
@@ -451,16 +451,7 @@ export const constantRoute = [
description: '在线数据存储单位换算工具,支持字节、KB、MB、GB、TB、PB、EB等存储单位之间的相互转换',
}
},
{
path: '/aes',
component: () => import('@/components/Tools/AesEncrypt/AesEncrypt.vue'),
name: 'aes',
meta: {
title: "AES加解密",
keywords: 'AES加密,AES解密,加密工具,解密工具',
description: '在线AES加解密工具,支持多种加密模式和填充方式,提供安全可靠的数据加密解密服务',
}
},
{
path: '/hashcalculator',
component: () => import('@/components/Tools/HashCalculator/HashCalculator.vue'),