fix
This commit is contained in:
@@ -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位、192位、256位密钥长度,可用于数据加密和解密。
|
|
||||||
</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>
|
|
||||||
@@ -161,15 +161,7 @@ export function getToolsCate() {
|
|||||||
cateId: 2,
|
cateId: 2,
|
||||||
cate: '开发运维',
|
cate: '开发运维',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'AES加解密',
|
|
||||||
logo: '/images/logo/md5.png',
|
|
||||||
desc: '在线AES加解密工具,支持多种加密模式和填充方式,提供安全可靠的数据加密解密服务',
|
|
||||||
url: '/aes/',
|
|
||||||
cateId: 2,
|
|
||||||
cate: '开发运维',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: 'Hash计算器',
|
title: 'Hash计算器',
|
||||||
@@ -179,15 +171,6 @@ export function getToolsCate() {
|
|||||||
cateId: 2,
|
cateId: 2,
|
||||||
cate: '开发运维',
|
cate: '开发运维',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: 'SHA1加解密',
|
|
||||||
logo: '/images/logo/sha1.svg',
|
|
||||||
desc: '在线SHA1哈希计算器,用于计算文本的SHA1哈希值',
|
|
||||||
url: '/sha1/',
|
|
||||||
cateId: 2,
|
|
||||||
cate: '开发运维',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
title: 'XML格式化',
|
title: 'XML格式化',
|
||||||
|
|||||||
+1
-10
@@ -451,16 +451,7 @@ export const constantRoute = [
|
|||||||
description: '在线数据存储单位换算工具,支持字节、KB、MB、GB、TB、PB、EB等存储单位之间的相互转换',
|
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',
|
path: '/hashcalculator',
|
||||||
component: () => import('@/components/Tools/HashCalculator/HashCalculator.vue'),
|
component: () => import('@/components/Tools/HashCalculator/HashCalculator.vue'),
|
||||||
|
|||||||
Reference in New Issue
Block a user