新闻中心
如何用J*aScript进行客户端数据加密与安全存储?
使用Web Crypto API可在前端实现数据加密,通过AES-GCM与PBKDF2结合密码加密字符串,生成密钥、salt和iv,确保数据在浏览器中临时安全存储,防止明文暴露。

在前端使用J*aScript进行数据加密和安全存储,虽然不能替代服务端安全措施,但在某些场景下可以增强用户体验和数据保护。由于浏览器环境的开放性,所有代码对用户可见,因此客户端加密主要用于防止明文数据暴露、提升临时数据安全性,而不是对抗恶意攻击者。
1. 使用Web Crypto API进行加密
现代浏览器提供了Web Crypto API,这是一个强大的内置加密工具,支持AES-GCM、RSA、SHA等算法,可用于对称和非对称加密。
示例:使用AES-GCM加密字符串
async function encryptData(plainText, password) {
const encoder = new TextEncoder();
const data = encoder.encode(plainText);
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12)); // GCM需要12字节IV
// 从密码生成密钥(PBKDF2)
const keyMaterial = await crypto.subtle.importKey(
'raw',
encoder.encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
const aesKey = await crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt: salt,
iterations: 100000,
hash: 'SHA-256'
},
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt']
);
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
aesKey,
data
);
// 返回salt、iv和密文(便于解密)
return {
salt: arrayBufferToBase64(salt),
iv: arrayBufferToBase64(iv),
cipherText: arrayBufferToBase64(encrypted)
};
}
function arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binary = '';
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
2. 安全地存储加密数据
加密后的数据仍需妥善保存。常见的前端存储方式包括localStorage、sessionStorage和IndexedDB,但它们都不安全,因为任何脚本都可以读取。
建议做法:
- 避免将敏感信息长期存在localStorage中,尤其是登录凭证或加密密钥。
- 若必须本地存储,应结合短期会话(如sessionStorage)与自动过期机制。
- 不要把加密密钥硬编码或明文存入前端,最好由用户输入口令动态生成。
例如,用户每次打开页面时输入一个“主密码”,用于解密本地加密数据,关闭后清除内存中的密钥。
MarsCode
字节跳动旗下的免费AI编程工具
339
查看详情
3. 解密数据并清理内存
解密过程是加密的逆操作,同样使用Web Crypto API。
async function decryptData(encryptedData, password) {
const decoder = new TextDecoder();
const salt = base64ToArrayBuffer(encryptedData.salt);
const iv = base64ToArrayBuffer(encryptedData.iv);
cons
t cipherText = base64ToArrayBuffer(encryptedData.cipherText);
const encoder = new TextEncoder();
const keyMaterial = await crypto.subtle.importKey(
'raw',
encoder.encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
const aesKey = await crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt: salt,
iterations: 100000,
hash: 'SHA-256'
},
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['decrypt']
);
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: iv },
aesKey,
cipherText
);
return decoder.decode(decrypted);
}
function base64ToArrayBuffer(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes.buffer;
}
注意:解密后得到的数据应尽快使用并从内存中清除,特别是密钥和明文敏感内容。可手动设置变量为null以帮助垃圾回收。
4. 安全边界与限制
必须清楚认识到J*aScript客户端加密的局限性:
- 无法防止中间人篡改或窃听,务必配合HTTPS。
- 攻击者可通过调试工具查看运行时变量,包括密钥和明文。
- 不能替代服务端身份验证和权限控制。
- 不适合保护高价值数据(如支付密钥、管理员密码)。
它更适合用于离线笔记类应用、配置加密、临时缓存保护等低风险场景。
基本上就这些。前端加密能增加一层防护,但核心安全逻辑始终应在服务端实现。
以上就是如何用J*aScript进行客户端数据加密与安全存储?的详细内容,更多请关注其它相关文章!
# 建设网站会员
# 如何使用
# 命令行
# 如何实现
# 离线
# 尤其是
# 但在
# 站群模式做seo
# 广告网站优化互联网推广
# 服务端
# 沙坡头区门户网站优化
# 薯条推广营销案例分享
# 新乡网站建设公司报价
# 景区线上推广营销
# 明星怎么加入网站推广
# 荆州本地网站优化排名
# 360营销推广排名前十
# 数据加密
# 如何用
# 有哪些
# 客户端
# se
# ai
# session
# 工具
# 字节
# 浏览器
# 编码
# 前端
# java
# word
# javascript
# 安全存储
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
夸克AO3官网入口_AO3镜像网站2025推荐
Go调试环境为何无法启动_Go调试器启动失败原因与解决策略
c++20的std::jthread是什么_c++可中断线程与RAII式管理
菜鸟取件码是什么怎么查 最全查询渠道汇总
XML中包含HTML标签导致解析错误? 正确嵌入非XML数据的两种方法
Golang切片为何属于引用类型_Golang slice底层结构与引用语义说明
蛙漫限时开放最深处链接_蛙漫全站漫画会员同款秒开地址
J*aScript中赋值与自增运算符的复杂交互与执行机制
J*aScript生成器_j*ascript异步迭代
怎么去除衣服上的口红印_生活小妙招教你用酒精轻松擦除
Golang如何实现容器化日志收集与分析_Golang容器日志收集分析方法
在React函数组件中利用原生HTML5进行邮箱地址验证
J*aScript数组对象转换:按指定键分组与值收集
基于动态规划的房屋花卉种植最小成本算法详解
厨房不锈钢水槽发黑生锈怎么处理_水槽用可乐+锡纸2分钟抛亮如新
J*aScript打印功能_j*ascript输出控制
邮编格式怎么匹配地址_根据邮编格式快速匹配详细地址的技巧
FullCalendar 自定义按钮样式定制指南
b站如何看历史记录_b站观看历史找回方法
Vue.js 图片显示异常排查:理解应用挂载范围与DOM ID唯一性
J*a里如何使用forEach遍历Map_Map遍历方法说明
荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】
AO3最新镜像入口 Archive of Our Own官方平台访问
Angular中单选按钮的正确使用与常见陷阱解析
J*a TimerTask中HashMap意外清空的深层原因与解决方案
c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学
steam官方网页快速访问 steam账号注册全流程
学习通网页版官方登录 超星学习通电脑端入口指南
J*aScript动态修改指定div内所有a标签样式指南
印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】
在J*a中如何使用Stream.map转换元素_Stream映射操作解析
优酷会员付费后没到账怎么办_优酷会员充值异常及解决方法
Composer中的^和~符号代表什么_精通Composer版本号语义化约束
CSS布局中意外空白:解决padding-top导致的顶部间距问题
Discord Slash 命令响应超时问题的异步解决方案
在J*aScript中复现SciPy的B样条拟合与求值:关键考量
Yandex搜索引擎官网入口_俄罗斯Yandex免登录一键直达
BetterDiscord插件中安全更新用户简介的实践指南
Tabulator表格日期时间排序问题及自定义解决方案
sublime如何只显示或隐藏特定类型文件_sublime侧边栏文件过滤
Win11怎么隐藏桌面图标 Win11一键隐藏所有桌面元素及恢复显示
蛙漫官网漫画入口地址_蛙漫在线畅读无广告弹窗
电脑IP地址怎么查 查看本机IP地址的几种方法
taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】
html怎么在cmd下运行php文件_cmd运行html中php文件方法【教程】
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
Golang如何实现状态模式管理对象状态_Golang State模式实现技巧
QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台
Win11怎么查看显卡显存 Win11显示适配器属性及专用视频内存查询
大象笔记网页版入口 印象笔记网页版登录入口


2025-10-13
浏览次数:次
返回列表
t cipherText = base64ToArrayBuffer(encryptedData.cipherText);
const encoder = new TextEncoder();
const keyMaterial = await crypto.subtle.importKey(
'raw',
encoder.encode(password),
{ name: 'PBKDF2' },
false,
['deriveKey']
);
const aesKey = await crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt: salt,
iterations: 100000,
hash: 'SHA-256'
},
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['decrypt']
);
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: iv },
aesKey,
cipherText
);
return decoder.decode(decrypted);
}
function base64ToArrayBuffer(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes.buffer;
}