IT评测·应用市场-qidao123.com

标题: 前端怎样安全存储密钥,防止信息走漏 [打印本页]

作者: 钜形不锈钢水箱    时间: 2024-12-15 01:51
标题: 前端怎样安全存储密钥,防止信息走漏
场景

把公钥硬编码在前端代码文件里,被公司安全检测到了要整改,于是整理几种常见的前端密钥存储方案。
1. 设置环境变量再读取

在打包或部署前端应用时,可以将密钥配置为环境变量,在应用运行时通过环境变量读取密钥。这样可以将密钥从源代码中分离出来,避免意外走漏。
a. 前端设置环境变量

将密钥作为前端应用的环境变量进行配置。但是直接使用环境变量存储密钥也是很危险的,前端代码可以被任何人查看和修改,这意味着敏感信息可能会被走漏。
步骤:

首先,在项目根目录下的 .env 文件中设置环境变量.
固然,你也可以设置在特定环境的 .env 文件,如 .env.production、.env.test等,这样可以根据不同的环境设置不同的变量值。
  1. VITE_API_KEY = 'your_api_key_here'
复制代码

但是使用这种方法打包后,秘钥仍能在源码中找到。
b. 后端设置环境变量

将密钥存储在后端环境变量中再由前端读取可以提高安全性,这样密钥不会在客户端暴露。

对于包含敏感信息的环境变量,应该避免将其暴露给前端。假如确实需要在前端使用某些敏感信息,思量使用更安全的机制,比如客户端证书或令牌。
2. 配置文件存储

将密钥存储在前端应用的配置文件中。在构建和部署应用时,可以将密钥配置为独立的配置文件,并在应用启动时读取配置文件中的密钥。
但是,在前端应用中使用配置文件来存储密钥也不是一个好的做法,因为前端代码(包罗配置文件)终极会被发送到用户的浏览器,这意味着任何有意图的攻击者都可以查看、修改甚至篡改这些配置。
3. 使用加密库加密存储

将密钥进行加密,并将加密后的密钥存储在前端应用中,应用在运行时解密密钥并使用。
这种方法可以提供更高的安全性,防止明文密钥走漏。
常见的做法是使用对称加密算法,将密钥与应用内部的固定值进行加密存储,并在需要使用时进行解密。

以下是一个示例,展示怎样使用 JavaScript 中的 CryptoJS 库进行加密和解密:
  1. // 导入 CryptoJS 库
  2. const CryptoJS = require('crypto-js');
  3. // 固定值,用于加密密钥
  4. const fixedValue = 'your_fixed_value';
  5. // 原始密钥
  6. const originalKey = 'your_secret_key_value';
  7. // 加密密钥
  8. const encryptedKey = CryptoJS.AES.encrypt(originalKey, fixedValue).toString();
  9. // 解密密钥
  10. const decryptedKey = CryptoJS.AES.decrypt(encryptedKey, fixedValue).toString(CryptoJS.enc.Utf8);
  11. console.log(decryptedKey); // 输出原始密钥
复制代码
加密存储并不是绝对安全的,它只是增加了密钥走漏的难度。对于高安全性要求的应用,发起将敏感操作放在服务器端进行,避免将加密密钥暴露给前端应用的客户端。
4. 混淆技术

混淆是防止JavaScript代码被轻易阅读和明白的有效方法,它通过一系列自动化的工具转换代码结构,但不改变其功能。混淆虽然提高了代码的保密性,但依然不能防止专业人员通过耐烦分析来明白代码。因此,它更多是增加攻击者的分析资本,而不是绝对的保护措施。
关于混淆,详细请看这篇:前端JavaScript代码混淆加密原理
5. 安全存储服务

将密钥存储在专门的密钥管理服务中,如密钥管理系统(Key Management System,KMS)。前端应用在运行时通过安全的协议和认证机制与密钥管理服务通信,获取需要的密钥。这样可以将密钥的管理和保护责任交给专门的服务,提供更高级别的安全性。
这也是一种将敏感数据安全地存储在后端服务器上的方法,以确保数据的保密性和完备性。
实际应用

综合来看,相对比力安全的是方法1b和5。
由于只是为相识决公司安全检测,故只选择了1a+3来存储密钥,其他方法可以思量作为后续优化方向。
此中CryptoJs库的使用:前端加密JS库–CryptoJS 使用指南
  1. // ------------env.d.ts------------
  2. declare const _MY_GLOBAL_KEY_: string
  3. // ------------vite.config.ts------------
  4. // base64加密后的密钥(注意,此处存储的密钥已经使用base64加密过了)
  5. const PRIVATE_KEY = "'xxxxxxxxxxxx'"
  6. export default defineConfig(({ command, mode }) => {
  7.   return {
  8.     // ......
  9.     // 定义全局常量,用于环境变量注入或其他编译时替换
  10.     define: {
  11.       _MY_GLOBAL_KEY_: PRIVATE_KEY
  12.     }
  13.   }
  14. })
  15. // ------------crypto.js------------
  16. import CryptoJS from 'crypto-js'
  17. import JSEncrypt from 'jsencrypt'
  18. const decryptKEY = CryptoJS.enc.Base64.parse(_MY_GLOBAL_KEY_).toString(CryptoJS.enc.Utf8) // Base64解密
  19. // rsa解密
  20. export function rsaDecrypt(decryStr) {
  21.   const decryptor = new JSEncrypt()
  22.   decryptor.setPrivateKey(decryptKEY)
  23.   const decrypted = decryptor.decrypt(decryStr)
  24.   return decrypted
  25. }
  26. // 发送请求获取token
  27. getTokenApi()
  28.   .then(res => {
  29.     const { resultData } = res
  30.     let decryptData = null
  31.     try {
  32.       decryptData = JSON.parse(CryptoJS.enc.Base64.parse(resultData).toString(CryptoJS.enc.Utf8))
  33.     } catch (error) {
  34.       console.log('error: ', error)
  35.     }
  36.     s3Data.value = decryptData
  37.     s3Data.value.ak = rsaDecrypt(decryptData.ak) //RSA解密
  38.     s3Data.value.sk = rsaDecrypt(decryptData.sk) //RSA解密
  39.     formData.bucketName = s3Data.value.bucketName
  40.     s3.value = new window.AWS.S3({
  41.       accessKeyId: s3Data.value.ak,
  42.       secretAccessKey: s3Data.value.sk,
  43.       endpoint: s3Data.value.endpoint,
  44.       sessionToken: s3Data.value.token
  45.     })
  46.   })
  47.   .catch(err => {
  48.     proxy.$errorHandle(err)
  49.   })
复制代码
拓展

Base64

常常在提到加密算法时看到Base64的使用,Base64的输入是二进制数据,输出是字符串,它是一种将二进制数据转换为字符的方法。通过Base64编码出的字符串只包含ASCII基础字符,如小写字母a-z、大写字母A-Z、数字0-9、符号"+“、”/"。
比方:字符串ShuSheng007对应的Base64为U2h1U2hlbmcwMDc=。此中=比力特殊,是添补符。
要注意的是,Base64不是加密算法,仅仅是一种编码方式,其算法也是公开的,以是并不能依赖它进行加密。

既然Base64不是加密算法,为什么加密算法又要使用它呢。
我们知道加密是将明文、可读的数据转换为加密的、无法阅读的乱码。然而,加密的输出是包含不可打印字符的二进制数据。为了安全传输或存储这些加密数据,需要把他们编码为能够正常处理的 ASCII 字符串。这就是 Base64 编码在加密算法中的作用。
此外,Base64编码是很适合在HTTP环境下使用的,因为HTTP是以传输文本为主的协议,而Base64算法恰好可以把传输内容变成文本。
而且由于base64的特性,其巨细增加很有限,编码后,不会明显扩大原有文件的巨细。
AES加密算法

高级加密标准(AES,Advanced Encryption Standard)是最常见的对称加密算法。
对称加密算法就是加密和解密用雷同的密钥,详细的加密流程如下图:

明文P
指没有经过加密的数据。
密钥K
用来加密明文的密码,在对称加密算法中,加密与解密的密钥是雷同的。
密钥为接收方与发送方协商产生的,但不可以直接在网络上传输,否则会导致密钥走漏。通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,对方再解密。
AES加密函数
把明文P和密钥K作为加密函数的参数输入,则加密函数会输出密文C。
密文C
经加密函数处理后的数据。
AES解密函数
把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

对称加密算法

对称加密算法的加密和解密用的密钥是雷同的。这种加密方式加密速度非常快,适合常常发送数据的场合。缺点是使用的密钥,它本身的传输比力麻烦,一样平常用非对称加密来传输。
非对称加密算法

非对称加密算法的加密和解密用的密钥是不同的。通常加密解密的速度比力慢,适合偶尔发送数据的场合。可以用非对称加密算法来串数对称加密算法使用的密钥。常见的非对称加密算法为RSA、ECC和EIGamal。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4