2019-07-17 jsencrypt加密和解密的那点事

最近在学习Vue+Node+Mongodb,索性就结合起来想做个个人博客,遇到的第一个坑就是如何在注册和登录的时候,给密码加密传给后台,后台解密。后续遇到的坑在慢慢梳理和总结哈
网上看了好多加密和解密的中间件,最终选择了使用jsencrypt,后台生成的公钥和私钥使用了node-rsa。简述一下前后端在这加密和解密的大致流程哈(至于原理级别的,暂不太清楚):
后台使用node-rsa生成公钥和私钥---->
后台写个获取公钥的接口(将公钥转化为指定格式)---->
前端调用接口获取公钥---->
前端使用JSEncrypt中间件设置公钥,并加密密码---->
前端将加密后的数据通过接口(如登录接口)传给后台---->
后台使用密钥加密前端加密的数据,在用解密后的数据查询或者保存到数据库中

1.安装包

"jsencrypt": "^3.0.0-rc.1",
"node-rsa": "^1.0.5",
备注:使用Node开发时,建议安装nodemon,可以热加载后台改的代码,超级好用,只需要安装一下包,在启动的使用nodemon app.js即可

2.后台生成公钥和密钥

const NodeRSA = require('node-rsa');
const fs = require('fs');
//生成公钥
function generator() {
    var key = new NodeRSA({ b: 512 })
    key.setOptions({ encryptionScheme: 'pkcs1' })

    var privatePem = key.exportKey('pkcs1-private-pem')
    var publicPem = key.exportKey('pkcs8-public-pem')

    fs.writeFile('./pem/public.pem', publicPem, (err) => {
        if (err) throw err
        console.log('公钥已保存!')
    })
    fs.writeFile('./pem/private.pem', privatePem, (err) => {
        if (err) throw err
        console.log('私钥已保存!')
    })
}
generator();

这样就可以在pem目录下生成两个文件:private.pem和public.pem,看文件名就知道谁是公钥谁是密钥了哈。

注意(此处有坑)---前端加密后的数据始终为false

之前自己也是在网上复制的代码,有一个地方有问题,对比一下哈


1.png

在导出公钥和密钥的时候,exportKey的参数相同,都为pkcs1,这就导致了前端获取到了公钥加密之后的数据为始终为false。找了好久才知道问题所在,追溯在node-rsa中的源码可以看到:


4.png

exportKey中的参数是有固定的值的,不然就会导致导出的公钥或者私钥有问题。

3.后台设置获取公钥接口供前端使用

router.get('/api/getPublicKey', (req, res) => {
    try {
        let publicKey = fs.readFileSync('./pem/public.pem', 'utf-8');
        console.log('publicKey', publicKey)
        res.send({ 'status': 0, 'msg': '公钥获取成功', 'resultmap': publicKey });
    } catch (err) {
        res.send(err);
    }
})

我使用的是Express中间件哈,使用Koa或者其他中间件的自行修改。

4.前端获取公钥并加密数据传给后台

import { JSEncrypt } from "jsencrypt";

  that.$axios
        .get(webUrl + "getPublicKey")
        .then(res => {
          if (res.data.status === 0) {
            let encryptor = new JSEncrypt();  //实例化
            encryptor.setPublicKey(res.data.resultmap); //设置公钥
            console.log(that.password);
            console.log(encryptor.encrypt(a));
            let data = {
              name: that.name,
              password: encryptor.encrypt(that.password), //加密
              nickName: that.nickName
            };
            that.$axios
              .post(webUrl + "admin/signUp", data)
              .then(response => {
                that.$message({
                  type: "success",
                  message: response.data.msg
                });
                if (response.data.status == 1) {
                  that.back();
                }
              })
              .catch(reject => {
                console.log(reject);
              });
          }
        })
        .catch(err => {
          console.log(err);
        });

5.后台用私钥解密

// 注册
router.post('/api/admin/signUp', (req, res) => {
    //是否重名
    db.User.find({ name: req.body.name }, (err, docs) => {
        if (err) {
            res.send(err);
            return
        }
        if (docs.length > 0) {
            res.send({ 'status': 0, 'msg': '用户名已注册' });
        } else {
            db.User.find({ nickName: req.body.nickName }, (err, docs) => {
                if (err) {
                    res.send(err);
                    return
                }
                if (docs.length > 0) {
                    res.send({ 'status': 0, 'msg': '昵称已注册' });
                } else {
                    const privateKey = fs.readFileSync('./pem/private.pem', 'utf8'); //读取私钥
                    let buffer1 = Buffer.from(req.body.password, 'base64'); //转化格式
                    let password = crypto.privateDecrypt({
                        key: privateKey,
                        padding: crypto.constants.RSA_PKCS1_PADDING // 注意这里的常量值要设置为RSA_PKCS1_PADDING
                    },  buffer1).toString('utf8');
                    console.log('解密之后的密码', password);
                    let newUser = new db.User({
                        name: req.body.name,
                        password: password,
                        nickName: req.body.nickName,
                        avatar: null,
                        // type: req.body.type
                        type: 2//1为管理员,2为游客,写死,新建管理员数据库直接改
                    });
                    newUser.save(function (err) {
                        if (err) {
                            res.send(err);
                        } else {
                            res.send({ 'status': 1, 'msg': '注册成功' });
                        }
                    })
                }
            })
        }
    })
})

经验证,后台解密后的密码和前端加密前的数据一致,说明加密和解密的过程都OK。加密和解密有很多种方法的,以上总结是自己尝过OK的一种,特此总结一下,希望能帮助到其他人。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容