Node 实现 rsa加密、解密、签名、验证

安装 node-rsa

npm install node-rsa
npm install @types/node-rsa -D

获取密钥对

const key = new NodeRsa({
   b: 512
})
const pubKey = key.exportKey('pkcs8-public')
const priKey = key.exportKey('pkcs8-private')

使用公钥对消息加密

const pubKey = new NodeRsa(publicKey, 'pkcs8-public')
const res = pubKey.encrypt(Buffer.from(data), 'base64')

使用私钥解密

const priKey = new NodeRsa(privateKey, 'pkcs8-private')
const res = priKey.decrypt(Buffer.from(data, 'base64'), 'utf8')

使用私钥对消息签名

const priKey = new NodeRsa(privateKey, 'pkcs8-private')
const signature = priKey.sign(Buffer.from(data)).toString('base64')

使用公钥验签

const pubKey = new NodeRsa(publicKey, 'pkcs8-public')
const res = pubKey.verify(data, Buffer.from(signature, 'base64'))

封装 & 测试

  • 封装 Rsa.ts
/**
 * zxj
 */

import NodeRsa from 'node-rsa'
import path from 'path'
import fs from 'fs'

export default class Rsa{
    private pubKey: string | null = null
    private priKey: string | null = null

    /**
     * 获取密钥对
     * @returns 返回 公钥和私钥
     */
    public getKeys(): {
        pubKey: string,
        priKey: string
    } {
        const key = new NodeRsa({
            b: 512
        })
        this.pubKey = key.exportKey('pkcs8-public')
        this.priKey = key.exportKey('pkcs8-private')
        return {
            pubKey: this.pubKey as string,
            priKey: this.priKey as string
        }
    }
    /**
     * 将密钥对写到文件
     * @param filepath 文件输出目录 [默认为程序运行目录]
     * @returns true: 写出成功 | false: 写出失败
     */
    public output(filepath?: string): boolean {
        if (!filepath) filepath = process.cwd() + path.sep
        filepath = filepath + path.sep
        try {
            fs.writeFileSync(
                filepath + 'rsa_pub',
                this.pubKey as string
            )
            fs.writeFileSync(
                filepath + 'rsa_pri',
                this.priKey as string
            )
            fs.writeFileSync(
                filepath + 'rsa_key',
                this.pubKey as string + '\n' + this.priKey as string
            )
            return true
        } catch (error) {
            return false
        }
    }
    /**
     * 使用公钥对消息加密
     * @param data 消息数据
     * @param publicKey 公钥 [默认为当前 rsa 对象公钥]
     * @returns 公钥加密后的数据 [base64加密的]
     */
    public encryptByPubKey(data: string, publicKey?: string): any {
        if (!publicKey) publicKey = this.pubKey as string
        if (!publicKey) return null
        try {
            const pubKey = new NodeRsa(publicKey, 'pkcs8-public')
            return pubKey.encrypt(Buffer.from(data), 'base64')
        } catch (error) {
            return null
        }
    }
    /**
     * 使用私钥解密
     * @param data 加密数据 [base64加密的]
     * @param privateKey 私钥 [默认为当前 rsa 对象私钥]
     * @returns 私钥解密后的数据
     */
    public decryptByPriKey(data: string, privateKey?: string): any {
        if (!privateKey) privateKey = this.priKey as string
        if (!privateKey) return null
        try {
            const priKey = new NodeRsa(privateKey, 'pkcs8-private')
            return priKey.decrypt(Buffer.from(data, 'base64'), 'utf8')
        } catch (error) {
            return null
        }
    }
    /**
     * 使用私钥对消息签名
     * @param data 消息数据
     * @param privateKey 私钥 [默认为当前 rsa 对象私钥]
     * @returns 签名数据 [base64加密的]
     */
    public signature(data: string, privateKey?: string): any {
        if (!privateKey) privateKey = this.priKey as string
        if (!privateKey) return null
        try {
            const priKey = new NodeRsa(privateKey, 'pkcs8-private')
            return priKey.sign(Buffer.from(data)).toString('base64')
        } catch (error) {
            return null
        }
    }
    /**
     * 使用公钥验签
     * @param data 消息数据
     * @param signature 签名数据 [base64加密的]
     * @param publicKey 公钥 [默认为当前 rsa 对象公钥]
     * @returns true: 验签成功 | false: 验签失败
     */
    public verify(data: string, signature: string, publicKey?: string): boolean {
        if (!publicKey) publicKey = this.pubKey as string
        if (!publicKey) return false
        try {
            const pubKey = new NodeRsa(publicKey, 'pkcs8-public')
            return pubKey.verify(data, Buffer.from(signature, 'base64'))
        } catch (error) {
            console.log(error)
            return false
        }
    }
    /**
     * 装载密钥对
     * @param pubKey 公钥
     * @param priKey 私钥
     * @returns true: 装载成功 | false: 装载失败
     */
    public setKeys(pubKey: string, priKey: string): boolean {
        if (!pubKey || !priKey) return false
        this.pubKey = pubKey
        this.priKey = priKey
        return true
    }
    /**
     * 从文件获取密钥(或私钥)
     * @param filepath 文件路径
     * @returns '': 获取失败 | 密钥(或私钥)
     */
    public static getKey(filepath: string): string {
        if (!filepath) return ''
        try {
            const key = fs.readFileSync(filepath, {
                encoding: 'utf-8'
            })
            return key
        } catch (error) {
            return ''
        }
    }

}
  • 测试 test.ts
import Rsa from '../Rsa'
// 从对象获取公钥和私钥
// const rsa = new Rsa()
// const keys = rsa.getKeys()
// console.log(keys)
// const res_en_by_pub = rsa.encryptByPubKey('hello')
// const res_de_by_pri = rsa.decryptByPriKey(res_en_by_pub)
// const res_sign_by_pri = rsa.signature('123456')
// const res_verify_by_pub = rsa.verify('123456', res_sign_by_pri)
// console.log('公钥加密:' + res_en_by_pub)
// console.log('私钥解密:' + res_de_by_pri)
// console.log('私钥签名:' + res_sign_by_pri)
// console.log('公钥验证:' + res_verify_by_pub)
// 从已有文件加载私钥和公钥
const rsa = new Rsa()
const pubKey = Rsa.getKey(process.cwd() + '\\' + 'rsa_pub')
const priKey = Rsa.getKey(process.cwd() + '\\' + 'rsa_pri')
const res_en_by_pub = rsa.encryptByPubKey('123456', pubKey)
const res_de_by_pri = rsa.decryptByPriKey(res_en_by_pub, priKey)
const res_sign_by_pri = rsa.signature('123456', priKey)
const res_verify_by_pub = rsa.verify('123456', res_sign_by_pri, pubKey)
console.log('公钥加密:' + res_en_by_pub)
console.log('私钥解密:' + res_de_by_pri)
console.log('私钥签名:' + res_sign_by_pri)
console.log('公钥验证:' + res_verify_by_pub)

写在最后

欢迎留言、私信、讨论;
文章有知识性错误请立马联系博主,博主将非常感谢;
无需经过允许即可随意使用转载,知识本来就是被广泛用来学习的;
非常感谢您能看到此处,本文为博主学习笔记,如有不同见解,请不吝赐教。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码绘世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值