写某自动化脚本时某统一认证系统 CAS (Central Authentication Service) 登录时采用了 js 对用户名和密码进行前端加密。
大致就是这么个东西:(╯°□°)╯︵ ┻━┻
function strEnc(data,firstKey,secondKey,thirdKey)
需要3个 key,似乎并不是常见的 DES加密。
因为比较着急用这个自动化程序,所以暂时不打算研究这段 867 行的代码。
于是找到了几个方便的在 Python 中调用 js 的好方法。
这里 PyV8 在 Python 3.9 测试会报错,官网只有 3.3 版本的,据说最高支持3.7(未测试),所以这里就不测试了。
在 Python 中使用本地 js 环境运行代码。
虽然目前已经停止更新维护了,不过还能用。
安装:
pip install PyExecJS
用法:
import execjs
context = execjs.compile(jsContent)
result = context.call("functionName", 'param1', 'param2')
官方文档:https://github.com/doloopwhile/PyExecJS
相当于用 node 命令执行 js 脚本,需要导出模块 (module.exports)。
安装:直接在 nodejs 官网下载安装包安装即可。
用法:
import os
pipeline = os.popen("node -e \"require('./jsFileName.js').functionName('param1','param2')\"")
result = pipeline.read().strip()
注意:此方法读出的输出结尾可能多一个空行。
纯 Python 写的 js 解释器,甚至支持把 js 代码直接翻译成 Python 代码。
安装:
pip install js2py
用法:
import js2py
context = js2py.EvalJs()
context.execute(jsContent)
result = context.functionName('param1', 'param2')
官方文档:https://github.com/PiotrDabkowski/Js2Py
测试代码:
import time
def readJson(file_name):
with open(file_name, 'r', encoding='UTF-8') as file:
result = file.read()
return result
js = readJson("des.js")
data = "string"
time.sleep(1)
print("---- Test of execjs ----")
T1 = time.perf_counter()
import execjs
context1 = execjs.compile(js)
res = context1.call("strEnc", data, '1', '2', '3')
T2 = time.perf_counter()
print("result: " + res)
print("Time: " + str((T2 - T1)*1000) + " ms.")
print("---- End of Test ----\n")
print("---- Test of js2py ----")
T1 = time.perf_counter()
import js2py
jsContext = js2py.EvalJs()
jsContext.execute(js)
rsa = jsContext.strEnc(data,'1','2','3')
T2 = time.perf_counter()
print("result: " + res)
print("Time: " + str((T2 - T1)*1000) + " ms.")
print("---- End of Test ----\n")
print("---- Test of nodejs ----")
jsn = js + '''
module.exports.strEnc = function(a,b,c,d) {
console.log(strEnc(a,b,c,d));
};
'''
with open("test.js", "w") as f:
f.write(jsn)
T1 = time.perf_counter()
import os
pipeline = os.popen(f"node -e \"require('./test.js').strEnc('{data}','1','2','3')\"")
res = pipeline.read().strip()
T2 = time.perf_counter()
print("result: " + res)
print("Time: " + str((T2 - T1)*1000) + " ms.")
print("---- End of Test ----\n")
print("---- Test of js2py translate ----")
T1 = time.perf_counter()
import js2py
js2py.translate_file('des.js', 'testPython.py')
T2 = time.perf_counter()
print("Translation ime: " + str((T2 - T1)*1000) + " ms.")
T1 = time.perf_counter()
import testPython
res = testPython.PyJsHoisted_strEnc_(data,'1','2','3')
T2 = time.perf_counter()
print("result: " + str(res))
print("Execute translated js: " + str((T2 - T1)*1000) + " ms.")
print("---- End of Test ----\n")
运行结果:
---- Test of execjs ----
result: 60755BA85B594627F34E71F4A9129CBF
Time: 512.5649999999999 ms.
---- End of Test ----
---- Test of js2py ----
result: 60755BA85B594627F34E71F4A9129CBF
Time: 2812.4174999999996 ms.
---- End of Test ----
---- Test of nodejs ----
result: 60755BA85B594627F34E71F4A9129CBF
Time: 113.34299999999953 ms.
---- End of Test ----
---- Test of js2py translate ----
Translation ime: 129.64780000000076 ms.
result: '60755BA85B594627F34E71F4A9129CBF'
Execute translated js: 2133.1337000000003 ms.
---- End of Test ----