首先附上连接:https://github.com/ecfexorg/w...node
因为工做缘由,前后进行过微信开放平台,企业微信,阿里钉钉的第三方开发。在这个过程当中都会有解密服务器推送来的消息的需求,并且通过这几回开发后,发现微信开放平台/企业微信/阿里钉钉的加密解密算法都是使用的 AES256,同时加密的消息体结构也是同样的。git
同时因为找到的第三方包的代码要么提供的功能太多,要么用了过期的 api,对于强迫症的我来讲很难忍受,因此本身造了一个轮子来解决这三方的消息加密解密的需求。github
使用的是 TypeScript 编写的,编译生成声明文件,用 vscode 开发能有良好的代码提示(不过这么简单的库貌似也没啥需求...)算法
下面说下用 TypeScript 开发一个 npm 项目而且发布到 npm 的构建和开发流程:typescript
1、首先在 github 上建立一个项目,项目名称最好和想要发布的 npm 包名一致,建立时能够选择是否生成 README 和证书,这里我就选择了 MIT 证书和默认的 README。npm
2、而后在本地使用git clone
命令将项目克隆下来,而后cd wx-ding-aes
,再执行npm init
,由于目录中包含了.git
文件夹,因此 npm 初始化时能够自动填入 github 地址,文档地址等 package 属性。json
咱们给生成的 package.json 文件的scripts
增长一条"build": "tsc"
,因而呆会儿执行npm run build
就能编译咱们的代码了。api
同时为了让别人使用咱们的库时也能有良好的代码提示,因此咱们编译时生成声明文件在types
文件夹下,发布时要连声明文件一块儿提交,同时还要在 package.json 中增长一个属性"types": "types/index.d.ts"
,意思是告诉别人这个库是自带声明文件的,而且声明文件的入口是在types
目录下的index.d.ts
里,固然若是你的"main"
的值不是index.js
,那么"types"
也要改变,让它能和"main"
对上号。服务器
3、初始化完成后,执行npm i typescript @types/node -D
安装 TypeScript 和 Node.js 标准库的声明文件。而后在touch tsconfig.json
建立 TypeScript 的配置文件,在 vscode 中编写 TypeScript 的配置文件会有属性名和属性值提示。微信
{ "compilerOptions": { "target": "es2017", "outDir": "dist", "module": "commonjs", "declaration": true, "declarationDir": "types" }, "include": [ "src" ] }
这里个人配置很简单,"target": "es2017"
表示编译目标的 JS 版本是 es2017;"outDir": "dist"
表示编译后的 JS 文件放在dist
文件夹中;"module": "commonjs"
表示编译后的 JS 仍是使用 commonjs 的模块系统;"declaration": true
和"declarationDir": "types"
表示编译时会自动生成声明文件,而且声明文件放在types
目录下。"include": [ "src" ]
表示 src
目录里面的文件会被编译。
注:Node.js 从 8.5 版本开始已经开始支持 es 模块系统,不过写这篇文章时还处于实验阶段,须要加上--experimental-modules
参数才能使用
4、准备工做作完,而后能够开始写代码了,我把全部的代码都放在src
目录下,写完后npm run build
就能看到自动生成的dist
文件夹里装着编译后的 JS 文件,而types
文件夹则装着自动生成的声明文件。
关于微信的加密解密逻辑,其使用的是标准的 aes-256 加密算法的 cbc 模式,算法是能够实现的,不过 node.js 的标准库提供的crypto
模块已经有了,因此咱们就不须要重复造轮子(有人看到这个名词确定会立刻跑去 npmjs.org 搜 aes256,可是我以为一个项目的依赖应该越少越好,毕竟别人写的东西质量可维护性都不可控)。aes-256 加密时,被加密的内容长度应该是 32 字节的倍数,若是不是 32 的倍数则须要进行补全。补全有不少种方式,最简单的是用 0x00 补全,可是微信要求用 pkcs7 进行补全,因此这里咱们也用这种方式(有人看到确定又会跑去 npmjs.org 搜 pkcs7 了...)。
简单几句话就能归纳这种补全方式:
假设被加密的内容长度为 x
两个例子:
这样作的目的是方便解密后截取原来的数据,解密后,只要看看最后一个数是多少(假设是 x ),那么就把最后的 x 个 byte 截掉就能获得前面被补全以前的数据了。上面的两个例子中,第一个只要看到最后一个数是 9 ,那就把最后 9 个 byte 去掉,前面的就是正确的内容,第二个例子之因此补 32 个 32 ,也是由于看到最后一个数是 32 ,那就把后面的 32 个 byte 截掉便可。假如由于已是 32 的倍数就不补全,那么就不知道是补全了的仍是没补全过的了。
代码就不一一解释,由于原理就在上面了。
5、写完后npm run build
就能编译了,若是想发布到 npmjs.org ,首先并非整个项目里的全部文件都要被发布的,发布到 npm 的话应该在package.json
的"files"
属性里选择哪些是想上传的,好比这个项目我之上传生成的 JS 和声明文件以及证书,由于源码是不必上传的。
若是没有 npm 账号的话,那么就要先注册一个 npm 的账号,而后在终端里执行npm login
登录你的账号。而后运行npm publish
便可发布,若是你担忧有时忘了编译就执行了publish
,能够在"scripts"
里面增长"prepublish": "npm run build"
,表示每次发布以前都会先自动执行编译脚本。更多的钩子命令能够在 npmjs.org 的官方文档查看。
6、
目前 npm 发布的包是没法使用npm unpublish <package name>
来进行下架了,只能经过npm deprecate
来标记过期,因此建议你们除非肯定本身有能力和精力去维护一个包,不然不要轻易发布一些乱七八糟的包,更不要去占一些本身没有能力维护的好的包名。若是实在想unpublish
,能够邮件联系 support@npmjs.com 说明缘由,他们会根据描述来进行处理。根据个人经验,因为时差,通常白天发邮件他们会深夜回复,而后你次日会收到回复。
但愿对你们有帮助 :P