1. 程式人生 > >Nodejs 微信加密訊息開發

Nodejs 微信加密訊息開發


最近在做微信接入,在採用明文訊息與微信伺服器進行通訊時,毫無壓力,改成密文後,微信提供了各種語言版本的demo,but 沒有nodejs。(複製一下,語文偏科,湊字數)。

做微信加密訊息主要下面幾個方面的內容:

  1. 加密前明文結構

  2. 16位元組的隨機字串

  3. 訊息長度的網路子節序

  4. 加密方式

  5. 加密演算法

  6. 填充塊計算方式

  7. 加密實現

1. 加密前明文結構: random(16B)+ msg_len(4B) + msg + $AppId;

        說明:random(16B)為16位元組的隨機字串;msg_len為msg長度,佔4個位元組(網路位元組序),$AppId為公眾賬號的AppId

2. 16位元組隨機字串:沒啥說的直接拼接就好了

var randomPrefix = function(n) {
    var _str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
    var buf = new Buffer(n);
    for (var i = 0; i < n; i++) {
        buf[i] = _str.charCodeAt(Math.floor(Math.random() * _str.length));
    }
    return buf;
};

3. 網路子節序:網路子節序根據訊息主體長度而生成
var htonl = function(n) {
    var buf = new Buffer(4);
    buf[0] = (n & 0xFF000000) >> 24;
    buf[1] = (n & 0x00FF0000) >> 16;
    buf[2] = (n & 0x0000FF00) >> 8;
    buf[3] = (n & 0x000000FF) >> 0;
    return buf;
};

4.加密方式:Base64_Encode(AES_Encrypt [random(16B)+ msg_len(4B) + msg + $AppId]);

5.加密演算法:AES採用CBC模式,祕鑰長度為32個位元組,資料採用PKCS#7填充;PKCS#7:K為祕鑰位元組數(採用32),buf為待加密的內容,N為其位元組數。Buf需要被填充為K的整數倍。在buf的尾部填充(K-N%K)個位元組,每個位元組的內容是(K- N%K);

6.填充塊計算方式: 訊息體長度 /32 ,

var padding = function(n) {
    var len = n % 32;
    if (len == 0) { 
        len = 32;
    } else {
        len = 32 - len;
    }
    var buf = new Buffer(len);
    for (var i = 0; i < len; i++) {
        buf[i] = len;
    }
    return buf;
};

7.加密實現:

    1.加密採用crypto庫,

    2.加密方式:aes-256-cbc,

    3.key:

var encodingAESKey = new Buffer("YfWVs4vtcNf6FPFRqzJ2VT6LCmpppePaRyGJjt7Rlcr" + "=", 'base64');

 4.IV:
encodingAESKey.slice(0, 16);

5. 建立加密物件方法:createCipheriv,
var cipher = crypto.createCipheriv('aes-256-cbc', encodingAESKey, encodingAESKey.slice(0, 16));

6. 取消自動填充
cipher.setAutoPadding(false);

7.加密並返回結果
cipher.update(Buffer.concat([preBuf, netBuf, msgBuf, corpBuf, paddingBuf]), "binary", 'base64') + cipher.final('base64'); // 解密資料

8.整體加密程式碼
var encrypt = function(msg) {
    var msgBuf = new Buffer(msg, "utf-8"),
        msgBufLength = msgBuf.length,
        preBuf = randomPrefix(16),
        netBuf = htonl(msgBufLength),
        corpBuf = new Buffer(corpId, "utf-8"),
        corpBufLength = corpBuf.length,
        paddingBuf = padding(20 + msgBufLength + corpBufLength);
    var cipher = crypto.createCipheriv('aes-256-cbc', encodingAESKey, encodingAESKey.slice(0, 16)); 
    cipher.setAutoPadding(false); // 取消自動填充
    return cipher.update(Buffer.concat([preBuf, netBuf, msgBuf, corpBuf, paddingBuf]), "binary", 'base64') + cipher.final('base64'); // 解密資料
};
歡迎加入node.js交流群:572416249
原文:http://my.oschina.net/lvyuely/blog/598421