wx
Version:
W(ei)X(in) -- (minimalist) WeChat Middleware for Express.js
133 lines (114 loc) • 4.08 kB
JavaScript
// Generated by CoffeeScript 1.10.0
(function() {
var PKCS7, Prpcrypt, WXBizMsgCrypt, crypto, generated_signature, xml2js;
crypto = require('crypto');
xml2js = require('xml2js');
PKCS7 = (function() {
var block_size;
block_size = 32;
return {
encode: function(data) {
var amount_to_pad, buf;
amount_to_pad = block_size - (data.length % block_size);
if (amount_to_pad === 0) {
amount_to_pad = block_size;
}
buf = new Buffer(amount_to_pad);
buf.fill(String.fromCharCode(amount_to_pad));
return Buffer.concat([data, buf]);
},
decode: function(data) {
var pad;
pad = data.readUInt8(data.length - 1);
if (pad < 1 || pad > 32) {
pad = 0;
}
return data.slice(0, data.length - pad);
}
};
})();
Prpcrypt = (function() {
var get_random_str;
function Prpcrypt(key) {
this.key = new Buffer(key + '=', 'base64');
}
get_random_str = function() {
var i, j, str, str_pol;
str = '';
str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
for (i = j = 0; j <= 15; i = ++j) {
str += str_pol[parseInt(Math.random() * str_pol.length)];
}
return str;
};
Prpcrypt.prototype.encrypt = function(text, appid) {
var buf, cipher, cipherChunks, iv, msg_len;
msg_len = 16 + 4 + Buffer.byteLength(text) + appid.length;
buf = new Buffer(msg_len);
buf.write(get_random_str(), 0);
buf.writeUInt32BE(Buffer.byteLength(text), 16);
buf.write(text, 20);
buf.write(appid, Buffer.byteLength(text) + 20);
iv = this.key.slice(0, 16);
buf = PKCS7.encode(buf);
cipher = crypto.createCipheriv('aes-256-cbc', this.key, iv);
cipher.setAutoPadding(false);
cipherChunks = [cipher.update(buf, 'binary', 'base64'), cipher.final('base64')];
return cipherChunks.join('');
};
Prpcrypt.prototype.decrypt = function(text, appid) {
var buf, decipher, iv, plainChunks;
iv = this.key.slice(0, 16);
decipher = crypto.createDecipheriv('aes-256-cbc', this.key, iv);
decipher.setAutoPadding(false);
plainChunks = [decipher.update(text, 'base64'), decipher.final()];
buf = Buffer.concat(plainChunks);
buf = PKCS7.decode(buf);
buf = buf.slice(20, buf.length - appid.length);
return buf.toString('utf8');
};
return Prpcrypt;
})();
generated_signature = function(token, timestamp, nonce, encrypt) {
var sha1;
sha1 = crypto.createHash('sha1');
sha1.update([token, timestamp, nonce, encrypt].sort().join(''));
return sha1.digest('hex');
};
WXBizMsgCrypt = (function() {
function WXBizMsgCrypt(token1, key1, appId) {
this.token = token1;
this.key = key1;
this.appId = appId;
if (this.key.length !== 43) {
throw 'Key is not valid.';
}
}
WXBizMsgCrypt.prototype.encrypt = function(msg, timestamp, nonce) {
var encrypt, pc, signature;
pc = new Prpcrypt(this.key);
encrypt = pc.encrypt(msg, this.appId);
signature = generated_signature(this.token, timestamp, nonce, encrypt);
return "<xml> <Encrypt><![CDATA[" + encrypt + "]]></Encrypt> <MsgSignature><![CDATA[" + signature + "]]></MsgSignature> <TimeStamp>" + timestamp + "</TimeStamp> <Nonce><![CDATA[" + nonce + "]]></Nonce> </xml>";
};
WXBizMsgCrypt.prototype.decrypt = function(msg, callback) {
return xml2js.parseString(msg, (function(_this) {
return function(err, result) {
var pc, xml;
if (err) {
throw err;
}
xml = result.xml;
if (xml.Encrypt) {
pc = new Prpcrypt(_this.key);
return xml2js.parseString(pc.decrypt(xml.Encrypt[0], _this.appId), callback);
} else {
return callback('Not encrypted.', null);
}
};
})(this));
};
return WXBizMsgCrypt;
})();
module.exports = WXBizMsgCrypt;
}).call(this);