RSA加密、解密,RSA数字签名和签名验证在真实项目中的应用

RSA是什么

      百度百科的解释为:RSA加密算法是一种非对称加密算法。在公开密钥加密电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

       简单点说则是加密和解密使用的是不同的秘钥,对称加密则是加密和解密都是使用相同的秘钥。本文只介绍RSA加密常规的使用方法,不涉及到加密原理及其底层实现。

 

RSA生成公钥/私钥对

      公钥和私钥一般是成对出现,就好像是一夫一妻制,一个男人只能有一个妻子,当然找小三除外。这就是一个约定,如果不按照约定来,加密和解密工作则不能顺利完成。使用rsa时首先需要生成公钥和私钥,JS代码如下:

/**
 * 生成公钥私钥对
 */
function  generateKeyPair () {
    let key = new NodeRSA({b: '512'});  //可以更改为1024
    key.setOptions({encryptionScheme: 'pkcs1'});// 指定加密格式
    let public_key = key.exportKey('pkcs8-public');
    let private_key = key.exportKey('pkcs8-private');

    console.log('公钥:\n', public_key);
    console.log('私钥:\n', private_key);

    return {
        public_key: public_key,
        private_key: private_key
    }

};

把512修改为1024后,生成的秘钥长度会有明显的变化,可以自己去设置不同的值看看结果。生成的秘钥非常长,并且含有换行符,如果想去掉换行符后直接保存在数据库中,则可以使用下面的代码:
        private_key = private_key.trim().split('\n').reduce((str, currentValue) => str + currentValue);
        public_key = public_key.trim().split('\n').reduce((str, currentValue) => str + currentValue);

 

RSA公钥加密/私钥解密

       这种应用方式的使用场景为项目中用户登录、重置密码、修改密码时使用,加载登录页面时,将公钥传递到登录页面,用一个隐藏标签保存公钥的值,然后在登录时,密码使用rsa加密传输。前端加密还需要一个加密文件jsencrypt.min.js,github上面有,或者去网上找一搜一大堆。在后端使用私钥解密,可以拿到用户登录时的明文密码,如果需要MD5加密后在进行密码校验,则完全可以放在后端进行。

前端公钥加密代码为:

let encrypt = new JSEncrypt();
encrypt.setPublicKey($('#public_key').val());
password = encrypt.encrypt(password);

后端私钥解密代码为:

/**
 * 解密数据
 * @param 加密后字符串
 * @param 私钥
 * @return {Buffer|Object|string}
 */
function decrypt (encryptData, private_key) {
    private_key = private_key || config.password_cfg.rsa_private_key;
    if (!private_key) throw "私钥不能为空";

    let prikey = new NodeRSA(private_key);
    prikey.setOptions({encryptionScheme: 'pkcs1'});
    return prikey.decrypt(encryptData, "utf-8");
};

 

RSA私钥加密/公钥解密

         据我了解RSA加密的常规用法是公钥加密,私钥解密。可是特殊场景则不能生搬硬套,需要灵活应对。自己在做一个接口项目的开发工作时,也使用到RSA加密,这里使用的则是私钥加密,然后使用公钥解密。因为这个加密工作是和签名和验证签名一起进行的,签名只能使用私钥,安全性非常有保障。

私钥加密代码:

/**
 * rsa 私钥加密数据
 * @param data 要加密的数据
 * @param private_key 私钥数据,如果为空,取配置文件的公钥数据
 * @return {string}
 */
const pkcsSize = '512';
const pkcsType = 'pkcs8';
const BASE64 = 'base64';
const UTF8 = 'utf8';
rsa_utils.encrypt = function (data, private_key) {
    if (!data){
        throw new Error("数据不能为空");
    }

    if (!private_key){
        throw new Error("私钥不能为空");
    }

    let key = new NodeRSA({ b: pkcsSize });
    key.importKey(private_key, pkcsType+'-private-pem');
    return key.encryptPrivate(data, BASE64, UTF8);
};

公钥解密代码:

/**
 * rsa 公钥解密数据
 * @param data 要解密的数据
 * @param public_key 公钥
 * @return {string}
 */

const pkcsType = 'pkcs8';
rsa_utils.decryptAPI = function (data, public_key) {
    if (!data){
        throw new Error("数据不能为空");
    }

    if (!public_key){
        throw new Error("公钥不能为空");
    }
    let key = new NodeRSA({ b: '512'});
    key.importKey(public_key, pkcsType+'-public-pem');
    return key.decryptPublic(data, UTF8);
};

 

RSA私钥签名/公钥验证签名

       签名和验证签名主要作用是确保数据在传输过程中不被串改,从而保证数据的安全性。这和人的签名有些类似,比如用支票去取钱时需要有钱人的签名,不然不让你取。

私钥签名代码:

/**
 * 数据签名
 * @param encryptData
 * @param public_key
 * @return {Buffer|Object|string}
 */
rsa_utils.sign = function (data, public_key) {
    if (!data){
        throw new Error("数据不能为空");
    }

    if (!public_key){
        throw new Error("公钥不能为空");
    }

    let key = new NodeRSA({ b: pkcsSize });
    key.importKey(public_key, pkcsType+'-private-pem');
    return key.sign(Buffer.from(data), BASE64).toString(BASE64);
};

公钥验证签名代码:

/**
 * 验证签名
 * @param data
 * @param private_key
 * @return {Buffer|Object|string}
 */

const pkcsType = 'pkcs8';
rsa_utils.validate = function (data, sign, public_key) {
    if (!data){
        throw new Error("数据不能为空");
    }

    if (!sign){
        throw new Error("签名不能为空");
    }

    if (!public_key){
        throw new Error("公钥不能为空");
    }

    let publicKey = new NodeRSA({ b: pkcsSize });
    publicKey.importKey(public_key, pkcsType+'-public-pem');
    return publicKey.verify(Buffer.from(data), sign, 'UTF-8', 'base64');
};

 

注意事项

      加密后的字符串或者是签名后的字符串中可能会含有加号,如果是将参数拼接在URL中进行传输时,需要特别注意。因为在解析时可能会将字符串中的加号解析为空格,这样的话解密就会出错。还有在使用过程中配置的参数一定要一致,如UTF-8和Base64这些参数,细节如果不注意,加密和解密就会出问题。

      如果有写得不对的地方,还请各位多多指点,留下各位宝贵的意见,欢迎在下面留言交流。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA加密解密RSA加密解密是一种非对称加密算法,它的原理是基于数学上的大素数分解难题,公钥和私钥是成对出现的,公钥可以公开,任何人都可以使用公钥对明文进行加密,但只有私钥的拥有者才能解密密文,保证了数据的安全性。RSA加密解密过程如下: 1. 选择两个大质数p和q,计算n = pq,φ(n) = (p-1)(q-1)。 2. 选择一个整数e,满足1<e<φ(n) 且e与φ(n)互质。 3. 计算d,使得d与e模φ(n)同余,即d * e ≡ 1 (mod φ(n)),d称为私钥。 4. 公钥为(n, e),私钥为(n, d)。 5. 加密过程:明文m经过加密后得到密文c,c = m^e mod n。 6. 解密过程:密文c经过解密后得到明文m,m = c^d mod n。 Diffie-Hellman密钥交换: Diffie-Hellman密钥交换是一种密钥交换协议,用于在公开信道上交换密钥。它的原理基于离散对数难题,其过程如下: 1. 选取一个大素数p和一个原根g。 2. Alice选择一个随机数a,计算A = g^a mod p,并将A发送给Bob。 3. Bob选择一个随机数b,计算B = g^b mod p,并将B发送给Alice。 4. Alice计算s = B^a mod p,Bob计算s = A^b mod p,两者得到相同的结果s,即为共享密钥。 RSA数字签名以及验证RSA数字签名是一种数字签名算法,它基于RSA加密解密算法。数字签名可以保证数据的完整性、来源可信和不可抵赖性。数字签名的过程如下: 1. 发送方使用自己的私钥对原始数据进行签名,得到数字签名。 2. 发送方将签名和原始数据一起发送给接收方。 3. 接收方使用发送方的公钥对签名进行验证,如果验证通过,则说明数据来源可信。 RSA数字签名验证过程: 1. 接收方使用发送方的公钥对签名进行解密,得到原始数据的哈希值。 2. 接收方对原始数据进行哈希运算,得到哈希值。 3. 比较步骤1和步骤2得到的哈希值,如果相同,则说明数字签名有效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值