首先附上連接: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