非对称加密,又称为公钥加密,是密码学中的一种加密方式,它涉及到
两个密钥
:一个公钥和一个私钥。公钥可以公开给任何人,而私钥必须严格保密。非对称加密在前端开发中主要用于安全通信和身份验证。JSEncrypt
是一个纯 JavaScript 库,用于实现非对称加密,即公钥和私钥加密。它允许你在浏览器端使用 RSA 加密,而不需要服务器端的任何支持
对称加密入口:前端加密之 CryptoJS学习文档【完整实例】
常见算法及使用场景
常见的非对称加密算法:
- RSA:
最常用
的非对称加密算法之一,广泛应用于安全数据传输和数字签名。 - ECC (椭圆曲线加密):一种相对较新的算法,相比 RSA,它在相同安全级别下需要更短的密钥长度,因此计算效率更高,资源消耗更少。
- DSA (数字签名算法):主要用于数字签名,而不是数据加密。
前端非对称加密的应用场景:
- HTTPS:在
HTTPS
协议中,服务器使用非对称加密技术与客户端建立安全连接。 - 数据加密:在不安全的通道上发送敏感信息时,可以使用接收方的公钥进行加密,确保只有接收方能够解密。
- 数字签名:用于验证数据的完整性和发送者的身份,常用于软件分发、电子合同等场景。
安装准备
钥匙对生成
openssl genrsa
是生成密钥的命令-out rsa_1024_priv.pem
将密钥输出到文件中
openssl genrsa -out rsa_1024_priv.pem 1024
# 查看文件密钥内容
cat rsa_1024_priv.pem
根据密钥生成对应公钥
openssl rsa
生成公钥-pubout
输出一个公钥-in file
根据输入的文件-out file
输出到某个文件
openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
# 查看公钥内容
cat rsa_1024_pub.pem
代码示例
安装加密库
npm i crypto-js jsencrypt
- 将公钥和私钥的内容进行存储,可以是文件也可以是字符串(
使用模版字符串,保证起格式
),并进行设置
let priv_key = `-----BEGIN RSA PRIVATE KEY----- ...```
let pub_key = `-----BEGIN PUBLIC KEY-----...```
let message = "Hello, World!";
var encrypt = new JSEncrypt()
encrypt.setPublicKey(pub_key)
var decrypt = new JSEncrypt()
decrypt.setPrivateKey(priv_key)
- 对消息进行验证,签名和验签的过程,
注意,必须是私钥进行签名,公钥进行验签
sign
需要指定散列函数。我们使用 CryptoJS 库中的一个,除非使用自定义散列函数,否则应该向 sign 方法提供散列类型。取值包括:md2、md5、sha1、sha224、sha256、sha384、sha512、等等。
// 签名, 用私钥
var signature = decrypt.sign(message, CryptoJS.SHA256, 'sha256')
console.log('签名', signature)
// 验签 用公钥
var uncrypted = encrypt.verify(message, signature, CryptoJS.SHA256)
console.log('验签', uncrypted)
- 加密解密
// 加密
let en_message = encrypt.encrypt(message)
console.log('加密结果:', en_message)
let de_message = decrypt.decrypt(en_message)
console.log('解密结果:', de_message)
完整代码实例
import JSEncrypt from 'jsencrypt'
import CryptoJS from 'crypto-js'
import { useEffect } from 'react'
export default function App() {
let priv_key = `-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDtW5HtwZ37JXlwSBHRYuL/MrOJFokKzIFOO1feoGUPyzcerWVQ
JYrvkOnpevlWQjqn7hy9cLlKEeo8BTwHRPFZa9ivbNQuiw3vt8HFY+v5jPx/Q9+c
Fmsl/B/A9pmyjjuqMAZxxME77lyEodxgxH8DZsg9MTGYlcqI/6IckmzCdwIDAQAB
AoGARABwFoXaFRHvcNO1ByAlmKeV+DiUmptskFVAH3AkhBnceNWEqSmYXHpQCaxJ
swTWeTYm1b9t1mK7kOaPBCYkXsTO3jopQLD60ds1QGfoR6eTgZdwXrsmTpb6Rnvy
+ldmo9pmfT4ssEtit9m4GVL9HvTN1xBsnM6+YZBgFZGkwsECQQD+QtRAO3UIj4bf
pJypQ0Q0Nb5+svCnBs/vrzKz0vSmysNu7/Vi/9wN5gime5P8G4RpJELNDhVld51I
w14rTPpbAkEA7vslVNo9deb5ZWD0aWNzk4Zh8YqbyhLxMNvrp1LtUcazCc8nyOoU
nR9J9wQLWZbYFENI1w3YHN1xPVZtcf/7FQJAEv2s2stWF3iY61VhOidDDd9BxjbZ
ULBqkY11bQcBrP+SD1Qu8OEJb6RR2xV53Se1ASFrN+OoZ3bCsa+d9f/+5wJAQY2g
kuL+gu3lsVpkENiX5nqxOSl1THvfrzBUNuS3dnwTtngdiK41E1h22IxCdMO85+oA
/ASvKFPR8SpZATFfdQJBANQ/D4h/8IZY6qQcZXnkY9eyoZhajKdt1lFEEj8WUUF5
ybua/Z9A37LaH3W8LddIkToIaO94eB5aXI+fatfvNc8=
-----END RSA PRIVATE KEY-----
`
let pub_key = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDtW5HtwZ37JXlwSBHRYuL/MrOJ
FokKzIFOO1feoGUPyzcerWVQJYrvkOnpevlWQjqn7hy9cLlKEeo8BTwHRPFZa9iv
bNQuiw3vt8HFY+v5jPx/Q9+cFmsl/B/A9pmyjjuqMAZxxME77lyEodxgxH8DZsg9
MTGYlcqI/6IckmzCdwIDAQAB
-----END PUBLIC KEY-----
`
useEffect(() => {
var encrypt = new JSEncrypt()
encrypt.setPublicKey(pub_key)
let message = 'hello world'
var decrypt = new JSEncrypt()
decrypt.setPrivateKey(priv_key)
// 签名, 用私钥
var signature = decrypt.sign(message, CryptoJS.SHA256, 'sha256')
console.log('签名', signature)
// 验签 用公钥
var uncrypted = encrypt.verify(message, signature, CryptoJS.SHA256)
console.log('验签', uncrypted)
// 加密
let en_message = encrypt.encrypt(message)
console.log('加密结果:', en_message)
let de_message = decrypt.decrypt(en_message)
console.log('解密结果:', de_message)
}, [])
return (
<div className="App">
<h1>加密数据</h1>
</div>
)
}