500 lines
14 KiB
JavaScript
500 lines
14 KiB
JavaScript
|
// 云函数入口文件
|
||
|
const cloud = require('wx-server-sdk')
|
||
|
var crypto = require('crypto');
|
||
|
var CryptoJS = require('crypto-js')
|
||
|
|
||
|
cloud.init({
|
||
|
traceUser: true,
|
||
|
env: "ipasswd-7h7iu"
|
||
|
})
|
||
|
|
||
|
const db = cloud.database()
|
||
|
|
||
|
function encoder(argv) {
|
||
|
var keys = new Array(4);
|
||
|
for (let i = 0; i < 4; i++) {
|
||
|
keys[i] = new Array(10);
|
||
|
}
|
||
|
keys[0] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "#"]
|
||
|
keys[1] = ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "#"]
|
||
|
keys[2] = ["a", "s", "d", "f", "g", "h", "j", "k", "l", "#", "#"]
|
||
|
keys[3] = ["z", "x", "c", "v", "b", "n", "m", "#", "#", "#", "#"]
|
||
|
|
||
|
var rtn = {
|
||
|
data: "",
|
||
|
arrgs: []
|
||
|
}
|
||
|
|
||
|
var pos = new Array(randomer(rtn.arrgs,3), randomer(rtn.arrgs,10))
|
||
|
var vec = new Array(0, 0), nvec = new Array(0, 0)
|
||
|
var getUpper = false, isUpperPoss = 0.2, allGetUpper = false
|
||
|
var getSpecial = false, isSpecialPoss = 0.1, allGetSpecial = false
|
||
|
for (let i = 0; i < argv.length; i++) {
|
||
|
nvec[0] = randomer(rtn.arrgs,50)
|
||
|
nvec[1] = randomer(rtn.arrgs,50)
|
||
|
vec[0] = nvec[0] * 0.08
|
||
|
vec[1] = nvec[1] * 0.24
|
||
|
if (possibility(rtn.arrgs, 0.5)) {
|
||
|
vec[0] *= -1
|
||
|
}
|
||
|
if (possibility(rtn.arrgs, 0.5)) {
|
||
|
vec[1] *= -1
|
||
|
}
|
||
|
pos = new Array(pos[0] + vec[0], pos[1] + vec[1])
|
||
|
if (pos[0] > 3.4 || pos[0] < 0) {
|
||
|
pos[0] = randomer(rtn.arrgs,3)
|
||
|
}
|
||
|
if (pos[1] > 10.4 || pos[1] < 0) {
|
||
|
pos[1] = randomer(rtn.arrgs,10)
|
||
|
}
|
||
|
var tstr = keys[Math.round(pos[0])][Math.round(pos[1])]
|
||
|
if(tstr == "#"){
|
||
|
i -= 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (argv.hasUpper == true){
|
||
|
if (possibility(rtn.arrgs, isUpperPoss)){
|
||
|
tstr = tstr.toUpperCase()
|
||
|
getUpper = true
|
||
|
allGetUpper = true
|
||
|
}
|
||
|
|
||
|
if ((i+2) == argv.length && allGetUpper == false) {
|
||
|
tstr = 'Z';
|
||
|
}
|
||
|
|
||
|
if(getUpper == false){
|
||
|
isUpperPoss *= 1.5
|
||
|
}
|
||
|
else{
|
||
|
getUpper = false
|
||
|
isUpperPoss *= 0.2
|
||
|
if(isUpperPoss < 0.1) isUpperPoss = 0.2
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (argv.hasSpecial == true) {
|
||
|
|
||
|
if (possibility(rtn.arrgs, isSpecialPoss)) {
|
||
|
var selectedSpecial = argv.specialChar;
|
||
|
var srand = randomer(rtn.arrgs, selectedSpecial.length)
|
||
|
tstr = selectedSpecial[srand]
|
||
|
getSpecial = true
|
||
|
allGetSpecial = true
|
||
|
}
|
||
|
|
||
|
if ((i+1) == argv.length && allGetSpecial == false) {
|
||
|
var selectedSpecial = argv.specialChar;
|
||
|
var srand = randomer(rtn.arrgs, selectedSpecial.length)
|
||
|
tstr = selectedSpecial[srand]
|
||
|
}
|
||
|
|
||
|
if (getSpecial == false) {
|
||
|
isSpecialPoss *= 1.5
|
||
|
}
|
||
|
else {
|
||
|
getSpecial = false
|
||
|
isSpecialPoss *= 0.1
|
||
|
if (isSpecialPoss < 0.05) isSpecialPoss = 0.1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rtn.data += tstr
|
||
|
|
||
|
}
|
||
|
return rtn
|
||
|
}
|
||
|
|
||
|
|
||
|
function decoder(argv, rands) {
|
||
|
var ridx = 0
|
||
|
var keys = new Array(4);
|
||
|
for (let i = 0; i < 4; i++) {
|
||
|
keys[i] = new Array(10);
|
||
|
}
|
||
|
keys[0] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "#"]
|
||
|
keys[1] = ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "#"]
|
||
|
keys[2] = ["a", "s", "d", "f", "g", "h", "j", "k", "l", "#", "#"]
|
||
|
keys[3] = ["z", "x", "c", "v", "b", "n", "m", "#", "#", "#", "#"]
|
||
|
|
||
|
var rtn = {
|
||
|
data: "",
|
||
|
arrgs: []
|
||
|
}
|
||
|
|
||
|
var pos = new Array(derandomer(rands[ridx++], 3), derandomer(rands[ridx++], 10))
|
||
|
var vec = new Array(0, 0), nvec = new Array(0, 0)
|
||
|
var getUpper = false, isUpperPoss = 0.2, allGetUpper = false
|
||
|
var getSpecial = false, isSpecialPoss = 0.1, allGetSpecial = false
|
||
|
for (let i = 0; i < argv.length; i++) {
|
||
|
nvec[0] = derandomer(rands[ridx++], 50)
|
||
|
nvec[1] = derandomer(rands[ridx++], 50)
|
||
|
vec[0] = nvec[0] * 0.08
|
||
|
vec[1] = nvec[1] * 0.24
|
||
|
if (depossibility(rands[ridx++], 0.5)) {
|
||
|
vec[0] *= -1
|
||
|
}
|
||
|
if (depossibility(rands[ridx++], 0.5)) {
|
||
|
vec[1] *= -1
|
||
|
}
|
||
|
pos = new Array(pos[0] + vec[0], pos[1] + vec[1])
|
||
|
if (pos[0] > 3.4 || pos[0] < 0) {
|
||
|
pos[0] = derandomer(rands[ridx++], 3)
|
||
|
}
|
||
|
if (pos[1] > 10.4 || pos[1] < 0) {
|
||
|
pos[1] = derandomer(rands[ridx++], 10)
|
||
|
}
|
||
|
var tstr = keys[Math.round(pos[0])][Math.round(pos[1])]
|
||
|
if (tstr == "#") {
|
||
|
i -= 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (argv.hasUpper == true) {
|
||
|
if (depossibility(rands[ridx++], isUpperPoss)) {
|
||
|
tstr = tstr.toUpperCase()
|
||
|
getUpper = true
|
||
|
allGetUpper = true
|
||
|
}
|
||
|
|
||
|
if ((i+2) == argv.length && allGetUpper == false) {
|
||
|
tstr = 'Z';
|
||
|
}
|
||
|
|
||
|
if (getUpper == false) {
|
||
|
isUpperPoss *= 1.5
|
||
|
}
|
||
|
else {
|
||
|
getUpper = false
|
||
|
isUpperPoss *= 0.2
|
||
|
if (isUpperPoss < 0.1) isUpperPoss = 0.2
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (argv.hasSpecial == true) {
|
||
|
|
||
|
if (depossibility(rands[ridx++], isSpecialPoss)) {
|
||
|
var selectedSpecial = argv.specialChar;
|
||
|
var srand = derandomer(rands[ridx++], selectedSpecial.length)
|
||
|
tstr = selectedSpecial[srand]
|
||
|
getSpecial = true
|
||
|
allGetSpecial = true
|
||
|
}
|
||
|
|
||
|
if ((i+1) == argv.length && allGetSpecial == false) {
|
||
|
var selectedSpecial = argv.specialChar;
|
||
|
var srand = derandomer(rands[ridx++], selectedSpecial.length)
|
||
|
tstr = selectedSpecial[srand]
|
||
|
}
|
||
|
|
||
|
if (getSpecial == false) {
|
||
|
isSpecialPoss *= 1.5
|
||
|
}
|
||
|
else {
|
||
|
getSpecial = false
|
||
|
isSpecialPoss *= 0.1
|
||
|
if (isSpecialPoss < 0.05) isSpecialPoss = 0.1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
rtn.data += tstr
|
||
|
|
||
|
}
|
||
|
return rtn
|
||
|
}
|
||
|
|
||
|
|
||
|
function possibility(args, possb){
|
||
|
var tmp = Math.random()
|
||
|
args.push(tmp)
|
||
|
if (possb > tmp){
|
||
|
return true;
|
||
|
}
|
||
|
else return false;
|
||
|
}
|
||
|
|
||
|
function depossibility(arg, possb) {
|
||
|
var tmp = arg
|
||
|
if (possb > tmp) {
|
||
|
return true;
|
||
|
}
|
||
|
else return false;
|
||
|
}
|
||
|
|
||
|
function randomer(args, range) {
|
||
|
var tmp = Math.random()
|
||
|
args.push(tmp)
|
||
|
return Math.floor(tmp * range);
|
||
|
}
|
||
|
|
||
|
function derandomer(arg, range) {
|
||
|
var tmp = arg
|
||
|
return Math.floor(tmp * range);
|
||
|
}
|
||
|
|
||
|
function aes_encrypt(data, openid, iv){
|
||
|
var blocks = parseInt(data.length / 16)
|
||
|
if (data.length % 16 != 0) blocks += 1;
|
||
|
buffdata = new Buffer(16 * blocks)
|
||
|
console.log("Blocks",blocks)
|
||
|
buffdata.write(data)
|
||
|
data = buffdata
|
||
|
console.log("Buffdata",buffdata)
|
||
|
|
||
|
var algorithm = 'aes-256-ecb'
|
||
|
var key = crypto.createHash('sha256').update(openid).digest('hex')
|
||
|
key = key.substr(0, 32)
|
||
|
key = key.toString('hex')
|
||
|
console.log("Data", data, "Key", key)
|
||
|
var clearEncoding = 'ascii'
|
||
|
var cipherEncoding = 'base64'
|
||
|
iv = iv || ""
|
||
|
var cipher = crypto.createCipher(algorithm, key, iv)
|
||
|
cipher.setAutoPadding(true);
|
||
|
var cipherChunks = []
|
||
|
cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
|
||
|
cipherChunks.push(cipher.final(cipherEncoding));
|
||
|
return cipherChunks.join('')
|
||
|
}
|
||
|
|
||
|
function aes_decode(ciphertext, openid, iv){
|
||
|
var algorithm = 'aes-256-ecb'
|
||
|
var key = crypto.createHash('sha256').update(openid).digest('hex')
|
||
|
key = key.substr(0, 32)
|
||
|
key = key.toString('hex')
|
||
|
console.log("Key", key)
|
||
|
var clearEncoding = 'ascii'
|
||
|
var cipherEncoding = 'base64'
|
||
|
iv = iv || "";
|
||
|
var decipher = crypto.createDecipheriv(algorithm, key, iv)
|
||
|
decipher.setAutoPadding(false);
|
||
|
console.log("crypted:" + ciphertext)
|
||
|
var cipherChunks = [];
|
||
|
cipherChunks.push(decipher.update(ciphertext, cipherEncoding, clearEncoding));
|
||
|
cipherChunks.push(decipher.final(clearEncoding));
|
||
|
var decrypted = cipherChunks.join('')
|
||
|
return decrypted;
|
||
|
}
|
||
|
|
||
|
// 云函数入口函数
|
||
|
exports.main = async (event, context) => {
|
||
|
const wxContext = cloud.getWXContext()
|
||
|
console.log("[云函数] 调用 " + event.method)
|
||
|
if (event.method == "encoder") {
|
||
|
var rtn = encoder(event.argv)
|
||
|
|
||
|
var code = String(wxContext.openid)
|
||
|
for (var i = 0; i < rtn.arrgs.length; i++) {
|
||
|
code += String(rtn.arrgs[i])
|
||
|
}
|
||
|
var handle_hash = crypto.createHash('sha256').update(code).digest('hex');
|
||
|
return new Promise((resolve, reject) => {
|
||
|
db.collection('passwd').add({
|
||
|
data: {
|
||
|
openid: wxContext.OPENID,
|
||
|
args: rtn.arrgs,
|
||
|
handle_hash: handle_hash,
|
||
|
argv: event.argv
|
||
|
}
|
||
|
}).then(res => {
|
||
|
if (res.errMsg == "collection.add:ok") {
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
passwd: rtn.data,
|
||
|
handle: handle_hash,
|
||
|
status: "ok"
|
||
|
})
|
||
|
}
|
||
|
else {
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
status: "fail"
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
else if (event.method == "saver") {
|
||
|
var handle = event.argv.handle
|
||
|
var openid = event.argv.openid
|
||
|
var tag = event.argv.tag
|
||
|
return new Promise((resolve, reject) => {
|
||
|
db.collection("passwd").where({
|
||
|
handle_hash: handle,
|
||
|
openid: openid
|
||
|
}).limit(1).get().then(res => {
|
||
|
console.log(res)
|
||
|
if (res.data.length > 0) {
|
||
|
var tag_hash = crypto.createHash('sha256').update(tag).digest('hex')
|
||
|
db.collection('passwd_saved').add({
|
||
|
data: {
|
||
|
openid: wxContext.OPENID,
|
||
|
args: res.data[0].args,
|
||
|
handle_hash: handle,
|
||
|
tag_hash: tag_hash,
|
||
|
argv : res.data[0].argv,
|
||
|
custom: false
|
||
|
}
|
||
|
}).then(res => {
|
||
|
if (res.errMsg == "collection.add:ok") {
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
handle: handle_hash,
|
||
|
status: "ok"
|
||
|
})
|
||
|
}
|
||
|
else {
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
status: "fail"
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
else if (event.method == "customer") {
|
||
|
var handle_hash = event.argv.handle
|
||
|
var openid = event.argv.openid
|
||
|
var tag = event.argv.tag
|
||
|
var passwd = event.argv.passwd
|
||
|
return new Promise((resolve, reject) => {
|
||
|
db.collection("passwd").where({
|
||
|
handle_hash: handle_hash,
|
||
|
openid: openid
|
||
|
}).limit(1).get().then(res => {
|
||
|
if (res.data.length > 0) {
|
||
|
|
||
|
var tag_hash = crypto.createHash('sha256').update(tag).digest('hex')
|
||
|
|
||
|
var key = crypto.createHash('sha256').update(openid).digest('hex')
|
||
|
key = key.substr(0, 32)
|
||
|
key = key.toString('hex')
|
||
|
|
||
|
var encrypt = CryptoJS.AES.encrypt(passwd, CryptoJS.enc.Utf8.parse(key), {
|
||
|
mode: CryptoJS.mode.ECB,
|
||
|
padding: CryptoJS.pad.Pkcs7
|
||
|
});
|
||
|
|
||
|
db.collection("passwd_saved").add({
|
||
|
data: {
|
||
|
openid: wxContext.OPENID,
|
||
|
ciphertext: encrypt.toString(),
|
||
|
handle_hash: handle_hash,
|
||
|
tag_hash: tag_hash,
|
||
|
custom: true
|
||
|
}
|
||
|
}).then(res => {
|
||
|
if (res.errMsg == "collection.add:ok") {
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
handle: handle_hash,
|
||
|
status: "ok"
|
||
|
})
|
||
|
}
|
||
|
else {
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
status: "fail"
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
else if (event.method == "decoder") {
|
||
|
var handle_hash = event.argv.handle
|
||
|
var openid = event.argv.openid
|
||
|
return new Promise((resolve, reject) => {
|
||
|
db.collection("passwd_saved").where({
|
||
|
handle_hash: handle_hash,
|
||
|
openid: openid
|
||
|
}).limit(1).get().then(res => {
|
||
|
console.log(res)
|
||
|
if (res.data.length > 0) {
|
||
|
if(res.data[0].custom){
|
||
|
var key = crypto.createHash('sha256').update(openid).digest('hex')
|
||
|
key = key.substr(0, 32)
|
||
|
key = key.toString('hex')
|
||
|
|
||
|
var decrypt = CryptoJS.AES.decrypt(res.data[0].ciphertext, CryptoJS.enc.Utf8.parse(key), {
|
||
|
mode: CryptoJS.mode.ECB,
|
||
|
padding: CryptoJS.pad.Pkcs7
|
||
|
});
|
||
|
resolve({
|
||
|
event,
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
passwd: decrypt.toString(CryptoJS.enc.Utf8),
|
||
|
status : "ok",
|
||
|
handle : handle_hash
|
||
|
})
|
||
|
}
|
||
|
else{
|
||
|
var args = res.data[0].args
|
||
|
var argv = res.data[0].argv
|
||
|
var rtn = decoder(argv,args)
|
||
|
resolve({
|
||
|
openid: wxContext.OPENID,
|
||
|
appid: wxContext.APPID,
|
||
|
passwd: rtn.data,
|
||
|
status: "ok",
|
||
|
handle: handle_hash
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
else if (event.method == "deleter"){
|
||
|
var handle_hash = event.argv.handle
|
||
|
var openid = event.argv.openid
|
||
|
return new Promise((resolve, reject) => {
|
||
|
if (wxContext.OPENID != openid){
|
||
|
resolve({
|
||
|
status: "failed",
|
||
|
openid : openid
|
||
|
})
|
||
|
}
|
||
|
var handle = handle_hash
|
||
|
var openid = openid
|
||
|
db.collection("passwd-saved").where({
|
||
|
handle: handle,
|
||
|
openid: wxContext.OPENID
|
||
|
}).get().then(res=>{
|
||
|
console.log(res)
|
||
|
if(res.data.length > 0){
|
||
|
db.collection("passwd-saved").doc(res.data[0]._id).remove().then(res => {
|
||
|
})
|
||
|
resolve({
|
||
|
status: "ok",
|
||
|
openid: openid
|
||
|
})
|
||
|
}
|
||
|
else{
|
||
|
resolve({
|
||
|
status: "failed",
|
||
|
openid: openid
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
|
||
|
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|