惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
AI
AI
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
N
News | PayPal Newsroom
G
GRAHAM CLULEY
V
Vulnerabilities – Threatpost
Cisco Talos Blog
Cisco Talos Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
P
Privacy & Cybersecurity Law Blog
Google DeepMind News
Google DeepMind News
L
LangChain Blog
T
Tailwind CSS Blog
腾讯CDC
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
Spread Privacy
Spread Privacy
月光博客
月光博客
WordPress大学
WordPress大学
C
CERT Recently Published Vulnerability Notes
小众软件
小众软件
AWS News Blog
AWS News Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
O
OpenAI News
W
WeLiveSecurity
H
Heimdal Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
V
Visual Studio Blog
The Last Watchdog
The Last Watchdog
有赞技术团队
有赞技术团队
量子位
TaoSecurity Blog
TaoSecurity Blog
V
V2EX
罗磊的独立博客
雷峰网
雷峰网
Latest news
Latest news
Jina AI
Jina AI
Simon Willison's Weblog
Simon Willison's Weblog
博客园_首页
博客园 - 聂微东
L
Lohrmann on Cybersecurity
V2EX - 技术
V2EX - 技术
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
Help Net Security
Help Net Security

LINUX DO - 最新话题

谷歌云盘下载700g数据集,求方法 OpenAI推出了100美元的Pro订阅后,plus的Codex 5小时限额大幅缩水 之前买的super grok居然还没掉 关于CPA认证文件周限 佬们,默认CDK的要求是什么等级啊? 最新版本的微信群聊机器人方案 有没有人知道如何free号没有封,那么是否可以循环使用,因为我看主要是周限 L站改版了?吓我一跳,我以为我浏览器崩了 淘宝这种宽带可信吗,500兆移动宽带月费8元到2099年 docker内部应用访问宿主机mysql和redis时被拒绝connection refuse Erp全栈想转行做Ai有什么推荐的吗 boost有bug 佬们,有没有靠谱点的 Plus 购买渠道 大妈,狗妈用的 lg 服务有源头开源项目吗? 有人有能过验证码打码的嘛 上次帖里好像发过通过大模型来打码的 gpt plus 封号似乎也太快了点,一天就给封号了 按流量/token收费的国产官方AI推荐 我算是知道了为什么Oracle总是ABC了 佬友们帮我分析一下 ChatGPT Team账号只有一个人使用和4个席位邀请满了使用的总额度是一样的吗? gpt-free 10个带rt CPA反代claude是默认1m吗? 我终于敢说我做出来windows上tmux的替代了,目标windows/全平台最强的终端Ai编程工具 claude pro升级max,除了原来的$20,好像还能再领一次$100 关于AI agent的知识框架 独乐乐不如众乐乐,分享一下我的的AI对话程序 佬们自建网站支付问题是怎么解决的 怎么能让gpt模仿claude风格输出 codex free已经死了,下一个会是plus或者team吗 请问chatgpt pro里的fast模式,速度快了,降智吗 天才程序员想要复活,还有可用的codex公益站么 里斯本丸沉没照进现代了 [富可敌国] [一叶知秋API]友仔们 我们换域名了~~ 记得更新一下哦 有点莫名其妙,被阿里云警告了 从道观回家之前,我和师兄问道 【picpi 皮皮公益站】为了防止有人拿去卖,邀请码发放规则更新。 美国 FAA: 我们需要你,游戏玩家,来当空管吧 vibe时用文言省tok吗? 有没有用? 会降表现吗? Codex CLI 官方这个 imagegen 的 Skill 到底是干啥的?哪有对应工具啊? 求问关于尼区和美区开通Claude 换设备登录telegram国内号码老账号 需要收费咋办? 发现hotmail的额度特别耐用 最近还有能正常用的claude中转站吗? 避雷闲鱼上面的CC中转站 现在cursor的优势是什么呢? OpenAI 回应马斯克要求罢免奥尔特曼:搞法律突袭,扰乱诉讼 谁在吹opencode go套餐啊,又慢量又少 【SamAltman】奥特曼被燃烧瓶袭击后的回应 咸鱼上359买的claude MAX 5x ,美国假家宽,看看能活几天 想问问跳蚤市场开的Pro和Plus 虚拟卡链接求助 [开源插件] 做了一个适合科研佬的GPT插件 【AI小说】拿AI跑了一部小说,佬们看看质量怎么样 总是能在首页看到opus4.6鞭尸推送 这个别名邮箱可以注册gpt 一个人在外地的话,佬们周末都做什么 你们ddg还能行不 获取不到新的邮箱 了····· claude code修复codex windows升级0.120.0 无法打开问题 我现在Zeabur上搭建了CPA服务,怎么再接入new api来做分发 杭州有么有佬友在搞AI应用这块的,四年前端转AI开发 汇丰、渣打两家银行获得香港稳定币牌照 【开源推广】 AIUsage:聚合多个 AI 平台配额与用量的 高颜值 macOS端 CPA看板 APP Newapi吃服务器内存多吗 中行跨境通疑限制无卡连续交易 或为应对盗刷 突然不能用表情回应话题了 codex是不是降额度了 反馈关于 “快问快答”标签的乱象 opencode版本1.4.3 无法上传图片问题 想问一下怎么解决这个问题,就是终端太多? codex更新到0.120.0之后无法加载以前的会话 sub2api怎么部署? 分享一个自用的南京继续教育平台视频自动播放下一集的油猴脚本 zotero9出来了 Claude正在向我推销付费项目,那能让你轻易得逞嘛 甲骨文用脚本开出来4个2+12咋办啊佬们,我还是免费号 各个厂的coding plan lite都绝版了? claude code 20美金账户问题 联通元景套餐续费问题 ai时代下的一些思考(诚邀大家讨论) 出境易GPT订阅pro求助 今年到目前股市的操作。 刚收到短信之前跑路的那家可以兑换了 佬们都用境外服务器做什么呢? 甲骨文4+24 求助领pro时候报错-付款页面出错。请重试。如果问题依然存在,请访问help.openai.com。 cloudflare 浏览器渲染增加了 CDP与mcp支持 SUB2API 导入 rt 时报错显示 Request failed with status code 502 如何解决 讨论一下怎么整理笔记 codex0.120.0更新后无法启动,回退 0.119.0正常使用 冰佬的公益站也不行了吗 三角洲直接给我封了10年 有佬友知道怎么起诉么 88VIP邀请 经过排查大概确定反重力代理报错问题了 【求助】openrouter 今年4月用国内visa卡充值后导致封禁,无法使用外国模型 奥特曼家被炸 自用,高信息量回复收集 求助sub2api分组问题 【新人报道】注册成功了 分享100个codex free账号 招聘 深圳客户端开发(flutter) 20k+
分享一个AES-256-CBC加解密网页源码
𝓕-𝓓𝓻𝓸𝓲� · 2026-04-28 · via LINUX DO - 最新话题
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> <title>AES-256-CBC 加解密工具 | 在线对称加密</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: linear-gradient(145deg, #1a1e2b 0%, #2a2f3f 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; font-family: 'Segoe UI', Roboto, system-ui, -apple-system, sans-serif; padding: 1.5rem; margin: 0; } .container { max-width: 750px; width: 100%; background: rgba(255, 255, 255, 0.07); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); border-radius: 2.5rem; padding: 2.2rem 2rem; box-shadow: 0 30px 50px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.15); transition: all 0.2s ease; } h1 { text-align: center; font-weight: 500; font-size: 2.1rem; letter-spacing: 2px; color: #e0e5f0; margin-bottom: 0.3rem; display: flex; align-items: center; justify-content: center; gap: 0.5rem; } h1 span { background: #3b82f6; color: white; font-size: 1rem; font-weight: 600; padding: 0.2rem 0.9rem; border-radius: 30px; letter-spacing: 0.5px; } .subtitle { text-align: center; color: #9aa4bf; margin-bottom: 2.2rem; font-size: 0.95rem; border-bottom: 1px dashed rgba(255,255,255,0.2); padding-bottom: 1.2rem; } .field { margin-bottom: 1.5rem; } label { display: flex; align-items: center; gap: 0.4rem; font-weight: 500; color: #cbd5e1; margin-bottom: 0.5rem; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.4px; } label i { font-style: normal; font-size: 1rem; } textarea, input { width: 100%; background: rgba(10, 15, 25, 0.7); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 1.2rem; padding: 0.9rem 1.2rem; font-size: 0.95rem; color: #f1f5f9; outline: none; transition: all 0.25s; font-family: 'Fira Code', 'JetBrains Mono', monospace; resize: vertical; backdrop-filter: blur(4px); } textarea:focus, input:focus { border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.35); background: rgba(20, 25, 40, 0.8); } textarea { min-height: 100px; } .key-wrapper { display: flex; gap: 0.6rem; align-items: center; } .key-wrapper input { flex: 1; } .icon-btn { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.25); color: #cbd5e1; padding: 0.7rem 1rem; border-radius: 1rem; font-size: 1.1rem; cursor: pointer; transition: 0.2s; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(8px); } .icon-btn:hover { background: rgba(59, 130, 246, 0.25); border-color: #3b82f6; color: white; } .actions { display: flex; gap: 1rem; margin: 2rem 0 1.2rem; flex-wrap: wrap; } .btn { flex: 1; min-width: 120px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.2); padding: 0.9rem 1.2rem; border-radius: 1.5rem; font-weight: 600; font-size: 1rem; color: #e2e8f0; cursor: pointer; backdrop-filter: blur(10px); transition: all 0.25s; display: flex; align-items: center; justify-content: center; gap: 0.4rem; letter-spacing: 0.5px; } .btn-encrypt { background: #2563eb; border-color: #3b82f6; box-shadow: 0 8px 18px -6px #1e3a8a; color: white; } .btn-encrypt:hover { background: #1d4ed8; border-color: #60a5fa; box-shadow: 0 10px 22px -6px #1e3a8a; } .btn-decrypt { background: #7c3aed; border-color: #8b5cf6; box-shadow: 0 8px 18px -6px #4c1d95; color: white; } .btn-decrypt:hover { background: #6d28d9; border-color: #a78bfa; } .btn-copy { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.25); } .btn-copy:hover { background: rgba(255, 255, 255, 0.18); border-color: #94a3b8; } .info-row { display: flex; justify-content: space-between; align-items: center; margin-top: 0.8rem; font-size: 0.8rem; color: #94a3b8; flex-wrap: wrap; gap: 0.5rem; } .badge { background: rgba(0,0,0,0.4); padding: 0.3rem 1rem; border-radius: 20px; backdrop-filter: blur(4px); } hr { border-color: rgba(255,255,255,0.1); margin: 1.2rem 0 0.8rem; } .footer-note { color: #7f8aa0; font-size: 0.8rem; text-align: center; } @media (max-width: 500px) { .container { padding: 1.5rem; } .actions { flex-direction: column; } } </style> </head> <body> <div class="container"> <h1> 🔐 AES-256-CBC <span>Crypto</span> </h1> <div class="subtitle">使用 Web Crypto API · 安全客户端加解密</div> <!-- 密钥输入 --> <div class="field"> <label><i>🔑</i> 密钥 (32字节 / 256位)</label> <div class="key-wrapper"> <input type="text" id="keyInput" placeholder="输入32字符密钥或点击生成随机密钥" autocomplete="off" spellcheck="false"> <button class="icon-btn" id="generateKeyBtn" title="生成随机256位密钥 (hex)">🎲</button> <button class="icon-btn" id="copyKeyBtn" title="复制密钥">📋</button> </div> <div class="info-row"> <span id="keyLengthIndicator">⚡ 长度: 0 / 32 字节</span> <span class="badge" id="keyStatus">未设置</span> </div> </div> <!-- 明文输入 --> <div class="field"> <label><i>📝</i> 明文 (Plaintext)</label> <textarea id="plaintextInput" placeholder="输入要加密的内容..."></textarea> </div> <!-- 密文输入 (Base64) --> <div class="field"> <label><i>🔒</i> 密文 (Base64格式)</label> <textarea id="ciphertextInput" placeholder="输入Base64密文进行解密..."></textarea> </div> <!-- 操作按钮组 --> <div class="actions"> <button class="btn btn-encrypt" id="encryptBtn">🔒 加密</button> <button class="btn btn-decrypt" id="decryptBtn">🔓 解密</button> <button class="btn btn-copy" id="copyCipherBtn">📋 复制密文</button> </div> <!-- 结果/状态信息 --> <div class="info-row" style="justify-content: center;"> <span id="operationStatus" class="badge" style="background: #1e293b;">⚪ 等待操作</span> </div> <hr> <div class="footer-note"> AES-256-CBC · 每次加密使用随机IV (16字节) · 密文格式: IV + 密文 (Base64) </div> </div> <script> (function() { // DOM 元素 const keyInput = document.getElementById('keyInput'); const plaintextInput = document.getElementById('plaintextInput'); const ciphertextInput = document.getElementById('ciphertextInput'); const encryptBtn = document.getElementById('encryptBtn'); const decryptBtn = document.getElementById('decryptBtn'); const generateKeyBtn = document.getElementById('generateKeyBtn'); const copyKeyBtn = document.getElementById('copyKeyBtn'); const copyCipherBtn = document.getElementById('copyCipherBtn'); const keyLengthIndicator = document.getElementById('keyLengthIndicator'); const keyStatus = document.getElementById('keyStatus'); const operationStatus = document.getElementById('operationStatus'); // ---------- 工具函数 ---------- function hexStringToUint8Array(hexString) { // 移除空格并确保小写 hexString = hexString.replace(/\s+/g, '').toLowerCase(); if (hexString.length % 2 !== 0) { throw new Error('十六进制字符串长度必须为偶数'); } const bytes = new Uint8Array(hexString.length / 2); for (let i = 0; i < hexString.length; i += 2) { const byte = parseInt(hexString.substr(i, 2), 16); if (isNaN(byte)) throw new Error('无效的十六进制字符'); bytes[i / 2] = byte; } return bytes; } function uint8ArrayToHexString(uint8Array) { return Array.from(uint8Array) .map(b => b.toString(16).padStart(2, '0')) .join(''); } // 生成随机16字节IV (用于CBC) function generateRandomIV() { return crypto.getRandomValues(new Uint8Array(16)); } // 将Base64字符串转换为Uint8Array function base64ToUint8Array(base64) { try { const binaryString = atob(base64); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes; } catch (e) { throw new Error('Base64解码失败:无效的Base64字符串'); } } // 将Uint8Array转换为Base64 function uint8ArrayToBase64(uint8Array) { let binaryString = ''; uint8Array.forEach(byte => { binaryString += String.fromCharCode(byte); }); return btoa(binaryString); } // 验证并获取CryptoKey (AES-256-CBC) async function getCryptoKeyFromHex(hexKey) { if (!hexKey || hexKey.trim() === '') { throw new Error('密钥不能为空'); } const cleanHex = hexKey.replace(/\s+/g, ''); if (cleanHex.length !== 64) { throw new Error(`密钥长度必须为64个十六进制字符 (32字节),当前长度: ${cleanHex.length}`); } if (!/^[0-9a-fA-F]{64}$/.test(cleanHex)) { throw new Error('密钥包含无效的十六进制字符'); } const rawKey = hexStringToUint8Array(cleanHex); return await crypto.subtle.importKey( 'raw', rawKey, { name: 'AES-CBC' }, false, ['encrypt', 'decrypt'] ); } // 更新密钥状态显示 function updateKeyIndicator() { const rawValue = keyInput.value.replace(/\s+/g, ''); const byteLength = rawValue.length / 2; keyLengthIndicator.textContent = `⚡ 长度: ${byteLength} / 32 字节 (${rawValue.length} hex字符)`; if (rawValue.length === 0) { keyStatus.textContent = '未设置'; keyStatus.style.color = '#f87171'; } else if (rawValue.length === 64 && /^[0-9a-fA-F]{64}$/.test(rawValue)) { keyStatus.textContent = '✅ 有效256位密钥'; keyStatus.style.color = '#4ade80'; } else { keyStatus.textContent = '❌ 格式无效'; keyStatus.style.color = '#fbbf24'; } } // 生成随机256位密钥 (hex) function generateRandomHexKey() { const randomBytes = new Uint8Array(32); crypto.getRandomValues(randomBytes); return uint8ArrayToHexString(randomBytes); } // 设置操作状态 function setStatus(message, isError = false) { operationStatus.textContent = message; operationStatus.style.color = isError ? '#fca5a5' : '#e2e8f0'; if (isError) { operationStatus.style.background = '#7f1d1d'; } else { operationStatus.style.background = '#1e293b'; } } // ---------- 加密操作 ---------- async function performEncrypt() { try { const plaintext = plaintextInput.value; if (plaintext === '') { throw new Error('明文不能为空'); } const keyHex = keyInput.value.trim(); const cryptoKey = await getCryptoKeyFromHex(keyHex); // 生成随机IV const iv = generateRandomIV(); // 将明文编码为Uint8Array (UTF-8) const encoder = new TextEncoder(); const plaintextBytes = encoder.encode(plaintext); // 执行加密 const encryptedBuffer = await crypto.subtle.encrypt( { name: 'AES-CBC', iv: iv }, cryptoKey, plaintextBytes ); // 组合 IV + 密文 const encryptedBytes = new Uint8Array(encryptedBuffer); const combined = new Uint8Array(iv.length + encryptedBytes.length); combined.set(iv, 0); combined.set(encryptedBytes, iv.length); // 转换为Base64 const base64Cipher = uint8ArrayToBase64(combined); ciphertextInput.value = base64Cipher; setStatus('✅ 加密成功 (IV已前置)'); } catch (error) { console.error('加密失败:', error); setStatus(`加密失败: ${error.message}`, true); // 不清空密文框,但提示错误 } } // ---------- 解密操作 ---------- async function performDecrypt() { try { const cipherBase64 = ciphertextInput.value.trim(); if (cipherBase64 === '') { throw new Error('密文不能为空'); } const keyHex = keyInput.value.trim(); const cryptoKey = await getCryptoKeyFromHex(keyHex); // 解码Base64得到 IV + 密文 const combined = base64ToUint8Array(cipherBase64); // 检查最小长度:至少需要16字节IV + 16字节块 (AES块大小) if (combined.length < 32) { throw new Error('密文数据太短,必须包含16字节IV和至少一个加密块'); } // 提取IV (前16字节) const iv = combined.slice(0, 16); // 提取密文 (剩余部分) const cipherData = combined.slice(16); // 执行解密 const decryptedBuffer = await crypto.subtle.decrypt( { name: 'AES-CBC', iv: iv }, cryptoKey, cipherData ); // 解码为UTF-8字符串 const decoder = new TextDecoder(); const plaintext = decoder.decode(decryptedBuffer); plaintextInput.value = plaintext; setStatus('🔓 解密成功'); } catch (error) { console.error('解密失败:', error); setStatus(`解密失败: ${error.message}`, true); // 解密失败不修改明文框 } } // 复制到剪贴板 async function copyToClipboard(text, elementDescription = '内容') { if (!text || text.trim() === '') { setStatus(`⚠️ 没有可复制的${elementDescription}`, true); return; } try { await navigator.clipboard.writeText(text); setStatus(`📋 已复制${elementDescription}到剪贴板`); } catch (err) { setStatus(`❌ 复制失败: ${err.message}`, true); } } // ---------- 事件绑定 ---------- keyInput.addEventListener('input', updateKeyIndicator); generateKeyBtn.addEventListener('click', () => { const newKey = generateRandomHexKey(); keyInput.value = newKey; updateKeyIndicator(); setStatus('🎲 已生成随机256位密钥'); }); copyKeyBtn.addEventListener('click', () => { const keyValue = keyInput.value.trim(); copyToClipboard(keyValue, '密钥'); }); encryptBtn.addEventListener('click', performEncrypt); decryptBtn.addEventListener('click', performDecrypt); copyCipherBtn.addEventListener('click', () => { const cipherValue = ciphertextInput.value.trim(); copyToClipboard(cipherValue, '密文'); }); // 可选:回车快捷操作(在密文框按Ctrl+Enter尝试解密,明文框Ctrl+Enter加密) plaintextInput.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 'Enter') { e.preventDefault(); performEncrypt(); } }); ciphertextInput.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 'Enter') { e.preventDefault(); performDecrypt(); } }); // 初始化状态显示 updateKeyIndicator(); // 设置一个默认示例密钥(方便测试,但提示用户可自行生成) // 使用一个固定的示例密钥 (32字节 hex) : "a1b2c3d4e5f6071829aabbccddeeff00112233445566778899aabbccddeeff" const defaultKey = "a1b2c3d4e5f6071829aabbccddeeff00112233445566778899aabbccddeeff"; if (keyInput.value === '') { keyInput.value = defaultKey; updateKeyIndicator(); setStatus('ℹ️ 已加载示例密钥,建议生成随机密钥'); } })(); </script> </body> </html> 在线使用 a5a3e081.pinme.dev AES-256-CBC 加解密工具 | 在线对称加密 1 个帖子 - 1 位参与者 阅读完整话题