非对称加密概念
- 乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都能获取,私钥则是保密的。
- 甲方获取乙方的公钥, 然后用它对信息进行加密。
- 乙方得到加密后的信息, 用私钥解密。
服务端
1、在node.js中使用rsa算法。首先需要是使用node-rsa包
npm install node-rsa
2、实现加密/解密
const http = require("http");
const NodeRSA = require("node-rsa");
let server = http.createServer().listen(3000,()=> {
console.log("Server running: 127.0.0.1:3000");
});
//生成密钥
const key = new NodeRSA({b: 2048}); //2048 密钥长度
key.setOptions({ encryptionScheme: 'pkcs1' });//指定加密格式 不改格式得话可能会报错
let router = ['/public_key', '/user'];
server.on('request', (req, res)=> {
res.setHeader('Access-Control-Allow-Origin', '*'); //这个表示任意域名都可以访问,这样写不能携带cookie了。
//res.header('Access-Control-Allow-Origin', 'http://www.baidu.com'); //这样写,只有www.baidu.com 可以访问。
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild , token');
res.setHeader('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');//设置方法
let url = req.url;
if(router.indexOf(url) == -1) {
res.end("404 NOT FOUND");
return;
}else {
let fun = url.split("/")[1];
if(fun == 'public_key') {
public_key(res);
}else {
user(req, res);
}
}
});
//发送公钥
function public_key(res) {
let arr = {
code: 200,
data: {
public_key: key.exportKey("pkcs8-public-pem"), //导出公钥
}
};
res.end(JSON.stringify(arr));
};
//获取私钥信息
function user(req, res) {
let data = "";
req.on('data', (chunk)=> {
data += chunk;
});
req.on('end', ()=> {
let buff = JSON.parse(data).password.replace(/\s+/g, '');
key.importKey(key.exportKey('pkcs8-private-pem')); //导入私钥
console.log(key.decrypt(buff, 'utf8')); //解密
res.end(JSON.stringify({code:200}))
})
}
客户端
客户端需要使用一个jsencrypt.min.js 包利用公钥对数据进行加密
<!DOCTYPE html>
<html>
<head>
<title>rsa</title>
</head>
<body>
<input type="text" placeholder="请输入用户名" id = "username">
<input type="password" placeholder="请输入密码" id = "password">
<button id = "btn">提交</button>
</body>
<script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.min.js">//需要引入一个rsa算法</script>
<script>
let username = document.querySelector("#username");
let password = document.querySelector("#password");
let btn = document.querySelector("#btn");
let url = "http://127.0.0.1:3000/public_key";
let url_user = "http://127.0.0.1:3000/user"
btn.onclick = function() {
fetch(url).then((res)=> {
res.json().then(data=> {
let encrypt = new JSEncrypt();
encrypt.setPublicKey(data.data.public_key)
const encryptKey = encrypt.encrypt(password.value); //使用公钥加密,得到密文
let arr = {
username: username.value,
password: encryptKey //encryptKey 格式为base64
};
fetch(url_user, {
method: "post",
body: JSON.stringify(arr)
}).then(res=> {
res.json().then(data=> {
console.log(data)
})
})
})
})
}
</script>
</html>
注意
以上运行时可以会出现如下错误
Error: Error during decryption (probably incorrect key). Original error: Error: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
出现如上错误的时候,是服务端的加密方法和jsencrypt的加密方式不一致导致的。jsencrypt加密方式是pkcs1,node-rsa 默认的加密方式是pkcs1_oaep。解决办法如下:
key.setOptions({ encryptionScheme: 'pkcs1' });//指定加密格式 不改格式得话可能会报错
网友评论