Node.js 使用 RSA 做加密

0 人评论
  作者: Avrit   分类:学习   浏览:910
RSA
RSA加密算法是一种非对称加密算法。

假设 A 与 B 通信。A 和 B 都提供一个公开的公钥。A 把需要传递的信息,先用自己的私钥签名,再用 B 的公钥加密。B 接收到这串密文后,用自己的私钥解密,用 A 提供的公钥验签。

为什么要先签名后加密?如果你先加密后签名,非法用户通过获取的公钥就可以破解签名,破解之后就可以替换签名。

详细的原理可以参考以下文档:
RSA算法原理(一)
RSA算法原理(二)

node-rsa
在 node.js 中使用 rsa 算法,我们使用的是 node-rsa 这个包。

const NodeRSA = require('node-rsa');

const a_public_key_data = '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----';
const a_private_key_data = '-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----';

const b_public_key_data = '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----';
const b_private_key_data = '-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----';

// 生成 A 的公私钥对象
const a_public_key = new NodeRSA(a_public_key_data);
const a_private_key = new NodeRSA(a_private_key_data);

// 生成 B 的公私钥对象
const a_public_key = new NodeRSA(a_public_key_data);
const a_private_key = new NodeRSA(a_private_key_data);

const text = 'Hello RSA!';

// 加签并加密
const sign = a_private_key.sign(text, 'base64', 'utf8');
console.log('A 私钥加签:', sign);

const encrypted = a_public_key.encrypt(sign, 'base64');
console.log('B 公钥加密:', encrypted);

// 解密并验签
const decrypted = a_public_key.decrypt(encrypted, 'utf8');
console.log('B 私钥解密:', decrypted);

const verify = a_public_key.verify(text, decrypted, 'utf8', 'base64');
console.log('A 公钥验签:', verify);
serialize
接口传递的一般是复杂的对象,所以我们需要把对象按一定的顺序排列并序列化成字符串再进行签名加密的操作

const serialize = (obj) => {
  const str = [];
  Object.keys(obj).sort().forEach((key) => {
    if (obj.hasOwnProperty(key)) {
      str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
    }
  });
  return str.join('&');
};
注意
RSA 算法有一定的计算量,加上 Node 不适合做计算密集型的操作。当接口被频繁调用可能会占用主线程,阻塞其他接口,使用了 RSA 的接口并发量会下降十倍左右。如非必要,谨慎在 Node 里使用 RSA。

node.js rsa加解密

0 人评论
  作者: Avrit   分类:学习   浏览:930
Node自带加解密的库crypto,不用安装第三方库就能实现加解密

util.js:

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

function generateKeys() {
  const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
    modulusLength: 4096,
    publicKeyEncoding: {
      type: 'pkcs1',
      format: 'pem',
    },
    privateKeyEncoding: {
      type: 'pkcs1',
      format: 'pem',
      cipher: 'aes-256-cbc',
      passphrase: '',
    },
  });
  fs.writeFileSync('private.cer', privateKey);
  fs.writeFileSync('public.cer', publicKey);
}

function encrypt(plain, pathToPublicKey) {
  const publicKey = fs.readFileSync(path.resolve(__dirname, pathToPublicKey), 'utf8');
  const buffer = Buffer.from(plain, 'utf8');
  return crypto.publicEncrypt(publicKey, buffer).toString('base64');
}

function decrypt(cipher, pathToPrivateKey) {
  const privateKey = fs.readFileSync(path.resolve(__dirname, pathToPrivateKey), 'utf8');
  const buffer = Buffer.from(cipher, 'base64');
  const plain = crypto.privateDecrypt({
    key: privateKey.toString(),
    passphrase: ''
  }, buffer);
  return plain.toString('utf8')
}


module.exports = {
  generateKeys,
  encrypt,
  decrypt
};
index.js:

const { generateKeys, encrypt, decrypt } = require('./utils');

generateKeys();
const cypher = encrypt('hello', 'public.cer');
console.log(cypher);
const plain = decrypt(cypher, 'private.cer');
console.log(plain);
输出:

> node index.js

VDWO5U8gdNmbS5/euzhr/Yx8NC8HBkHR40obxMm+EtnXXw2dq+ojmbet1mxYg/x8mSrkMHV6a+zbmjkF0y9XP7euZnNJug1SiDCgfTF2ctcjjnJVWREsuub/JORcIHTqpHLnYCBuCyceazP5KFyJk1IRSDev09/8Hn5wWjLzcOHEU/qR5QANFPQ0
skyQqRhvkyKwWLSODosycJebqrC8xvfcFPpDSRUe64qNv5EIU/sB9RYfqbjNa5psyVrcjnaL7oSPDwINxtlqNcL6a3D1GKOdJJWbluuxllKEia9m1tsufpoh4abvigIFCBXWrTuMKHQuBbBifRWjQdFbqlLkb6aTvlzHDiCbuYg0FU3jEps7FSwk
utOjREDRMCmCAsoMt8trJuP9hkpZa4q18o3YLKvGYQLwFrbw5WrWSauAuxTz9Wb7T9WZXJOgrP+bymB7rwZxMvBhkXxtQtbB8kuGwoXu6o6e/0mXKsaaOKzQs9g7EyrUwVs8ane5J1OI9n5F76MfPWbz0NbfbIwRv0V2HoSAvJY+oWPrYjvyPkou
0KwsnmG9egSGCIkglqyrbfQ1pmLoxzOzjFrrKEpkXWuN9NZv8Inucb87VcDr23XkLo72Rh05mYn8YSECF/2GIREcDadU+gVSaoRl2v+K+iv4XYeePg/M4SVCsj4oc0aAgaE=
hello

centos安装node环境

0 人评论
  作者: Avrit   分类:学习   浏览:1367

一、安装wget

yum install -y wget

二、下载node最新的安装包

wget https://nodejs.org/dist/v12.13.0/node-v12.13.0-linux-x64.tar.xz

三、依次执行下面命令解压安装包

xz -d node-v12.13.0-linux-x64.tar.xztar -xf node-v12.13.0-linux-x64.tar

 

安装xz,

yum install xz 即可

四、部署bin文件,即全局配置node环境

ln -s ~/node-v12.13.0-linux-x64/bin/node /usr/bin/nodeln -s ~/node-v12.13.0-linux-x64/bin/npm /usr/bin/npm

 

五、测试

node -v
npm -v

 

补充:

查看linux服务器信息

uname -v

删除软连接

rm -rf /usr/bin/npmrm -rf /usr/bin/node

 配置淘宝镜像

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

 全局配置cnpm

ln -s ~/node-v12.13.0-linux-x64/bin/cnpm /usr/bin/cnpm

TypeScript基础类型,类实例和函数类型声明

0 人评论
  作者: Avrit   分类:学习   浏览:1040

TypeScript(TS)是微软研发的编程语言,是JavaScript的超集,也就是在JavaScript的基础上添加了一些特性.其中之一就是类型声明.

一、基础类型

TS的基础类型有 Boolean,Number,String,Array,Tuple,Enum,Any,Void,Null,Undefined,Never,Object.

==布尔类型 Boolean==

let isDone: boolean = false *在变量名后用冒号:T(T 代表TS的类型)声明变量的类型。

==数字类型 Number==

阅读全文>>

typescript进阶篇之高级类型与条件类型(Readonly, Partial, Pick, Record)

0 人评论
  作者: Avrit   分类:学习   浏览:1200

高级类型
lib 库中的五个高级类型
以下所有例子皆以 person 为例

interface Person {
    name: string;
    age?: number;
}
Partial
源码:

type Partial<T> = {
    [P in keyof T]?: T[P];
};

阅读全文>>

JavaScript的排序算法——选择排序

0 人评论
  作者: Avrit   分类:学习   浏览:1018

选择排序(Selection Sort)

选择排序是一种排序算法,是一个占用常用内存(In-place)的排序方法。时间复杂度为O(n2)。通常情况下,在处理大型数据的时候,性能要比相似的插入排序低。选择排序因其简单性而著称,并且在某些情况下性能要优于更复杂的算法,尤其是在辅助存储空间有限的情况下。

原理

选择排序的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。

选择排序(Selection Sort)

选择排序(Selection Sort)

复杂度

算法 最好情况 平均情况 最坏情况 空间复杂度 稳定性
选择排序 O(n2) O(n2) O(n2) O(1) 不稳定

ES6实现

function SelectionSort(originalArray) {     const array = [...originalArray];     let len = array.length;     for (let i = 0; i < len - 1; i++) {       let  minIndex = i;         for (let j = i + 1; j < len; j++) {             if (array[j] < array[minIndex]) {                 minIndex = j;             }         }        if (minIndex != i) {            [array[minIndex], array[i]] = [array[i], array[minIndex]]        }     }     return array; } 

参考

维基百科
百度百科

相关阅读

JavaScript的排序算法——冒泡排序
JavaScript的排序算法——选择排序
JavaScript的排序算法——插入排序
JavaScript的排序算法——归并排序
JavaScript的排序算法——快速排序

JavaScript的排序算法——冒泡排序

0 人评论
  作者: Avrit   分类:学习   浏览:1066

冒泡排序(Bubble Sort)

冒泡排序,有时也被称做沉降排序,是一种比较简单的排序算法。这种算法的实现是通过遍历要排序的列表,把相邻两个不符合排列规则的数据项交换位置,然后重复遍历列表,直到不再出现需要交换的数据项。当没有数据项需要交换时,则表明该列表已排序。

冒泡排序(Bubble Sort)

复杂度

算法 最好情况 平均情况 最坏情况 空间复杂度 稳定性
冒泡排序 O(n) O(n2) O(n2) O(1) 稳定

ES6实现

  1. 普通版冒泡排序
function BubbleSort(array) {     let len = array.length;     for (let i = 0; i < len; i++) {         for (let j = 0; j < len-i-1; j++) {             if (array[j]> array[j+1]) {                 [array[j],array[j+1]] = [array[j+1],array[j]];             }          
        }  
    }  
    return array; } 
  1. 优化版冒泡排序
function BubbleSort(originalArray) {     const array = [...originalArray];     let swapped;     for (let i = 0; i < array.length; i++) {        swapped = true;        for (let j = 0; j < array.length - i - 1; j++) {            if (array[j] > array[j+1]) {             [array[j],array[j+1]] = [array[j+1],array[j]]             swapped = false;            }        }         if (swapped) {             break;         }     }     return array; } 
https://www.jianshu.com/p/2fd84fadab5f

mongoose --- populate主要操作以及简单和$lookup对比

0 人评论
  作者: Avrit   分类:学习   浏览:1256
简单的创建声明三张表:user/department/project

const UserSchema = new mongoose.Schema({
  username: { type: String, required: true },
  password: { type: String, required: true },

阅读全文>>

JS中substr与substring的区别

0 人评论
  作者: Avrit   分类:学习   浏览:812
js中substr和substring都是截取字符串中子串,非常相近,可以有一个或两个参数。

语法:substr(start [,length]) 第一个字符的索引是0,start必选 length可选

   substring(start [, end]) 第一个字符的索引是0,start必选 end可选

相同点:当有一个参数时,两者的功能是一样的,返回从start指定的位置直到字符串结束的子串

var str = "hello Tony";

str.substr(6);  //Tony

str.substring(6); //Tony

 

不同点:有两个参数时

(1)substr(start,length) 返回从start位置开始length长度的子串

“goodboy”.substr(1,6);   //oodboy

【注】当length为0或者负数,返回空字符串

(2)substring(start,end) 返回从start位置开始到end位置的子串(不包含end)

“goodboy”.substring(1,6);  //oodbo

【注】:

(1)substring 方法使用 start 和 end 两者中的较小值作为子字符串的起始点

(2)start 或 end 为 NaN 或者负数,那么将其替换为0

另外:ECMA 并没有对 substr() 进行标准化,所以并不建议使用 substr()

Object.prototype.toString.call()方法

0 人评论
  作者: Avrit   分类:学习   浏览:1070

在JavaScript里使用typeof判断数据类型,只能区分基本类型,即:number、string、undefined、boolean、object
对于null、array、function、object来说,使用typeof都会统一返回object字符串。
要想区分对象、数组、函数、单纯使用typeof是不行的。在JS中,可以通过Object.prototype.toString方法,判断某个对象之属于哪种内置类型。
分为null、string、boolean、number、undefined、array、function、object、date、math。

1. 判断基本类型

Object.prototype.toString.call(null); // "[object Null]" Object.prototype.toString.call(undefined); // "[object Undefined]" Object.prototype.toString.call(“abc”);// "[object String]" Object.prototype.toString.call(123);// "[object Number]" Object.prototype.toString.call(true);// "[object Boolean]" 

2. 判断原生引用类型

**函数类型** Function fn(){   console.log(“test”); } Object.prototype.toString.call(fn); // "[object Function]" 
**日期类型** var date = new Date(); Object.prototype.toString.call(date); // "[object Date]" 
**数组类型** var arr = [1,2,3]; Object.prototype.toString.call(arr); // "[object Array]" 
**正则表达式** var reg = /[hbc]at/gi; Object.prototype.toString.call(reg); // "[object RegExp]" 
**自定义类型** function Person(name, age) {     this.name = name;     this.age = age; } var person = new Person("Rose", 18); Object.prototype.toString.call(arr); // "[object Object]" 

无法区分自定义对象类型,自定义类型可以采用instanceof区分

console.log(person instanceof Person); // true 

3.判断原生JSON对象

var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON); console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是;