密钥对生成 使用内置模块crypto 从 node.js 的 v10.12.0 开始,可以使用内部模块 crypto.generateKeyPairSync 方法生成公私钥。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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来生成:
1 2 3 4 5 6 7 8 9 const key = new nodeRSA ({b : 1024 });const publicKey = key.exportKey ('public' );const privateKey = key.exportKey ('private' );console .log ('publicKey>>>>>>' ,publicKey);console .log ('privateKey>>>>>>' ,privateKey);
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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):
1 2 * `'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
或者,使用已存在的私钥来生成公钥:
1 2 3 4 5 6 7 8 9 10 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const crypto = require ('crypto' );const nodeRSA = require ('node-rsa' );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);console .log ('加密后:' , encrypt.toString ('base64' ));console .log ('解密后:' , decrypt.toString ());
输出:
1 2 加密后: m6HOwaF//jDW9PvXJwgx3gipV54Ia1pPsiR1+qRXkiy7ZNxrogMt+O6+6NwRL15qsNZM/suCeB6gn9uxFOtby58MzsYOMUiZGDWbfafRawypX5lEY6GEY/EdwuveLU97XkIHUpJ424CN2x6vxw6LdQjKBeyPbFI0Pw19Et5FSuc= 解密后: hello ashin!
使用RSA 1 2 3 4 5 6 7 8 9 10 11 12 const nodeRSA = require ('node-rsa' );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 ());
输出:
1 2 加密后: 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 签名/认证如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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);
输出:
1 2 3 4 >>>>>>>>>>使用 crypto 签名>>>>>>>>>> PARviHlEefrUcroa2DsyvlRDInMvHzSWASL6Jb9IQ9zMf7mobVMrOP5pMnt/WhB5VMzt7AmlQkNRVm4+dmtmn3ow9BDZ+ZU8l8iRmoIDO89BgQHSCQJp8YRQ6cmo8JXjswBPMAurnlcVr0IxUkmewgv2E7INuOTYn9tgiOrjZ8k= >>>>>>>>>>使用 crypto 签名验证>>>>>>>>>> true
使用rsa 1 2 3 4 5 6 7 8 9 10 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' ));
输出:
1 2 3 4 >>>>>>>>>>使用 node-rsa签名>>>>>>>>>> PgwpNyMeCnSuguTm3O2ftFzO6Hh1T966jHuMQf4pUTKcqSjRTkehET5JMMEQfMepjDVlrt1xPBR8ZO7Hej4RlnZ4sGP+hQW4qSuDGqcgeZIp6+8oMtgJ5V/QqcfY81K7NXojzTDep7oQ2UzRWOyRcl1JO6BmhqHMEkuemTyPuIM= >>>>>>>>>>使用 node-rsa签名验证>>>>>>>>>> true