• nodejs之RSA加密/签名


    nodejs之RSA加密/签名

    密钥对生成

    使用内置模块crypto

    从 node.js 的 v10.12.0 开始,可以使用内部模块 crypto.generateKeyPairSync 方法生成公私钥。

    const { generateKeyPairSync } = require('crypto');
    const { publicKey, privateKey } = generateKeyPairSync('rsa', {
      modulusLength: 4096,
      publicKeyEncoding: {
        type: 'spki',
        format: 'pem'
      },
      privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem',
        cipher: 'aes-256-cbc',
        passphrase: 'top secret'
      }
    });
    

    使用node-rsa库

    低版本(< v10.12.0)的话可以使用node-rsa来生成:

    // 生成一个1024长度的密钥对
    const key = new nodeRSA({b: 1024});
    // 导出公钥
    const publicKey = key.exportKey('public');
    // 导出私钥
    const privateKey = key.exportKey('private');
    
    console.log('publicKey>>>>>>',publicKey);
    console.log('privateKey>>>>>>',privateKey);
    

    输出如下:

    publicKey>>>>>> -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLANd0RbDjBb9R5o1ng5y1WRpf
    VnX+xuVd0BY7ZyFzzlq8L05PGMbfElxLqWGqvtmEspOPZibd+6i05D+xePoF4k7h
    GYLmdJW2JJdqLVCWCKbVBPAlI7PS9XoRKea1czL0syNd10l+TdXJ4r/ES4vMn33m
    JzCGuueIhRjcqalGowIDAQAB
    -----END PUBLIC KEY-----
    privateKey>>>>>> -----BEGIN RSA PRIVATE KEY-----
    MIICXwIBAAKBgQDLANd0RbDjBb9R5o1ng5y1WRpfVnX+xuVd0BY7ZyFzzlq8L05P
    GMbfElxLqWGqvtmEspOPZibd+6i05D+xePoF4k7hGYLmdJW2JJdqLVCWCKbVBPAl
    I7PS9XoRKea1czL0syNd10l+TdXJ4r/ES4vMn33mJzCGuueIhRjcqalGowIDAQAB
    AoGBAMDxRtZDGrFbmBCusX1OMRaH3rH4imOiBQSaL1c8WSYpXkH4MFSrNvF0EPb0
    wVg41qLx25/ytkRL2Xg8bHEwi2h030SsQAgQnb/8kXOztS3vE3ujOJmji6B+5/2e
    cnZjrgOxkb8U5PwNdFalpUqpXGDxsxfem7ej537Xv23cBqHZAkEA55I4+w7cpOlT
    X1bw5A5ODJE8+WHptmSzAso7YTxaGgOFv415hr4tnxH3Oj+BL4bqlhLyh0QXgUqo
    PCtRBjgLpwJBAOBrHmDj/4zhZYj/0OyrA7069ktEEezEfYYHKeYbt1CA6gxPB+Qk
    UVvndY2cQNR0ItIHYixgSnOR15ZegcoQnKUCQQDWpkeDD8eeZVkOqrwn6MqYA5iN
    YSEOHFGCaIqaGyM5scIsSKs5JteK91A/AdZxg5G3AmEk2Q0gn19KRqyYIyNJAkEA
    kaRzHqZZHvDYmESNLkr+Ljypwsb2axZJ8EWN54xtN42yVzKjCGiZdG+OVszlNfv4
    7R1llS8YolAv/aJv0NdfEQJBALdZzBkUOwS8sfnjh8BOtEGhTwgHxF7IrXk875mJ
    4JaKMWJYhki27TzqIskSlY7luemXFKRB3pxagB8kUeVFzdQ=
    -----END RSA PRIVATE KEY-----
    

    ps:如果不指定导出格式,公钥默认是pkcs8,私钥是pkcs1。关于这两个格式简单描述(具体可以参考README.md):

    * `'pkcs1'` — public key starts from `'-----BEGIN RSA PUBLIC KEY-----'` header and private key starts from `'-----BEGIN RSA PRIVATE KEY-----'` header
     * `'pkcs8'` — public key starts from `'-----BEGIN PUBLIC KEY-----'` header and private key starts from `'-----BEGIN PRIVATE KEY-----'` header
    

    或者,使用已存在的私钥来生成公钥:

    const fs = require('fs');
    const nodeRSA = require('node-rsa');
    
    // 读取私钥
    const privateKey = fs.readFileSync('./certs/ca-key.pem', 'utf8');
    const key = new nodeRSA(cakey);
    // 导出对应公钥
    const publicKey = key.exportKey('pkcs1-public-pem');
    console.log(privateKey);
    console.log(publicKey)
    

    RSA加密

    使用crypto

    最简单的方法,使用自带模块crypto:

    const crypto = require('crypto');
    const nodeRSA = require('node-rsa');
    
    // 生成一个1024长度的密钥对
    const key = new nodeRSA({b: 1024});
    // 导出公钥
    const publicKey = key.exportKey('public');
    // 导出私钥
    const privateKey = key.exportKey('private');
    
    const secret = 'hello ashin!'
    // 使用私钥加密,公钥解密
    const encrypt = crypto.privateEncrypt(privateKey, Buffer.from(secret));
    const decrypt = crypto.publicDecrypt(publicKey, encrypt);
    
    // 也可反过来
    // const encrypt = crypto.publicDecrypt(publicKey, Buffer.from(secret));
    // const decrypt = crypto.privateEncrypt(privateKey, encrypt);
    
    console.log('加密后:', encrypt.toString('base64'));
    console.log('解密后:', decrypt.toString());
    

    输出:

    加密后: m6HOwaF//jDW9PvXJwgx3gipV54Ia1pPsiR1+qRXkiy7ZNxrogMt+O6+6NwRL15qsNZM/suCeB6gn9uxFOtby58MzsYOMUiZGDWbfafRawypX5lEY6GEY/EdwuveLU97XkIHUpJ424CN2x6vxw6LdQjKBeyPbFI0Pw19Et5FSuc=
    解密后: hello ashin!
    

    使用node-rsa

    const nodeRSA = require('node-rsa');
    
    // 生成一个1024长度的密钥对
    const key = new nodeRSA({b: 1024});
    
    const secret = 'hello ashin!'
    
    const encryptd = key.encrypt(secret);
    const decryptd = key.decrypt(encryptd)
    
    console.log('加密后:', encryptd.toString('base64'));
    console.log('解密后:', decryptd.toString());
    

    输出:

    加密后: lypj+J4qvRaNIQpe6bAaMc8NV2kwlh9Uzn6zdkI1Cda4PKECP8AD/aANUhW2qNB6vxtSwD5xDBLak/9LYAmADavu2F4kxDDvepfd6L4F1+JShsrxWHF/OGY1LyoLtPkSfK6DtJcDqtSv/X/PZ7hAcTgyBRnpwPFKKgplikqt8OI=
    解密后: hello ashin!
    

    RSA签名

    rsa签名一般用于web api的安全验证,防止请求被篡改。

    一般我们需要对请求参数(包括params、body、协议等)做一定规则处理(客户端与服务端预定好规则),然后请求头带上签名,服务端拿到签名后进行验签。

    node客户端发起请求时可以使用urllib库的请求钩子快速生成签名,然后加到请求头headers里面:

    beforeRequest Function - Before request hook, you can change every thing here.

    使用crytpo

    签名/认证如下:

    const crypto = require('crypto');
    
    console.log('>>>>>>>>>>使用 crypto 签名>>>>>>>>>>');
    const sign = crypto.createSign('SHA256');
    sign.update('hello ashin!');
    sign.end();
    const signature = sign.sign(privateKey);
    console.log(signature.toString('base64'));
    
    console.log('>>>>>>>>>>使用 crypto 签名验证>>>>>>>>>>');
    const verify = crypto.createVerify('SHA256');
    // 对具体数据验证
    verify.update('hello ashin!');
    verify.end();
    const data = verify.verify(publicKey, signature);
    console.log(data);
    

    输出:

    >>>>>>>>>>使用 crypto 签名>>>>>>>>>>
    PARviHlEefrUcroa2DsyvlRDInMvHzSWASL6Jb9IQ9zMf7mobVMrOP5pMnt/WhB5VMzt7AmlQkNRVm4+dmtmn3ow9BDZ+ZU8l8iRmoIDO89BgQHSCQJp8YRQ6cmo8JXjswBPMAurnlcVr0IxUkmewgv2E7INuOTYn9tgiOrjZ8k=
    >>>>>>>>>>使用 crypto 签名验证>>>>>>>>>>
    true
    

    使用node-rsa

    const nodeRSA = require('node-rsa');
    
    const key = new nodeRSA({b: 1024});
    console.log('>>>>>>>>>>使用 node-rsa签名>>>>>>>>>>');
    const signature = key.sign('hello ashin!');
    console.log(signature.toString('base64'));
    
    console.log('>>>>>>>>>>使用 node-rsa验签>>>>>>>>>>');
    const verify = key.verify('hello ashin!', signature);
    console.log(verify.toString('base64'));
    

    输出:

    >>>>>>>>>>使用 node-rsa签名>>>>>>>>>>
    PgwpNyMeCnSuguTm3O2ftFzO6Hh1T966jHuMQf4pUTKcqSjRTkehET5JMMEQfMepjDVlrt1xPBR8ZO7Hej4RlnZ4sGP+hQW4qSuDGqcgeZIp6+8oMtgJ5V/QqcfY81K7NXojzTDep7oQ2UzRWOyRcl1JO6BmhqHMEkuemTyPuIM=
    >>>>>>>>>>使用 node-rsa签名验证>>>>>>>>>>
    true
    
  • 相关阅读:
    beta版本冲刺七
    beta版本冲刺六
    beta版本冲刺五
    beta版本冲刺四
    beta版本冲刺三
    Beta版本冲刺(二)
    项目评测
    beta版本冲刺(一)
    福大软工 · 最终作业
    福大软工 · 第十二次作业
  • 原文地址:https://www.cnblogs.com/wzs5800/p/13169306.html
Copyright © 2020-2023  润新知