Python encryption and Java calling scheme

Python encryption and Java calling scheme

createBy lln
updateTime 2021-09-28

encryption scheme

官方网站
http://www.pyinstaller.org
官网文档
https://pyinstaller.readthedocs.io/en/stable/
参考博客
https://www.cnblogs.com/weix-l/p/10881373.html
https://zhuanlan.zhihu.com/p/85760495
https://blog.csdn.net/x_w_haohan/article/details/99233561
https://blog.csdn.net/Iv_zzy/article/details/107462210
https://blog.csdn.net/qq_16104903/article/details/90444269
https://blog.csdn.net/qq_41699621/article/details/103596742

Windows

pyinstaller packaging method

#安装pyinstaller
pip install pyinstaller
PyInstaller提供了两种把.py文件包成.exe文件的方式:
第一种:把由.py文件打包而成的.exe文件及相关文件放在一个目录中。
语法:pyinstaller 应用程序
eg:pyinstaller Hello.py
第二种:加上 -F 参数后把制作出的.exe打包成一个独立的.exe格式的可执行文件。
语法:pyinstaller -F 应用程序
eg:pyinstaller -F Hello.py 
虽然扩平台,但是pyinstaller也只能在当前操作系统中运行,比如你用mac只能打包出mac上的可执行脚本,要是你想打包出windwos电脑上的可执行程序,你就要用windows执行打包命令。

如果你的脚本文件中包含其他脚本,比如hello.py包含自定义脚本(world.py)或是系统脚本(sys.py):则需要在打包的时候加上其他脚本的路径。通过-p指定第三方包的路径,一条路径对应一个-p
eg:pyinstaller -F -p C:\SystemLib\site-packages -p C:\MyLib Hello.py
执行一次打包命令通常会生成两个目录一个附件,分别是build、dist、和xx.spec。build是编译过程中的中间产物,dist是最终可执行程序目录,spec文件是类似缓存,如果你第二次打包,则需要先把spec删掉,否则第二次打包会受影响。
参数介绍
-a:不包含编码.在支持Unicode的python版本上默认包含所有的编码
-c:使用控制台子系统执行(默认)(只对Windows有效)
-d:产生debug版本的可执行文件
-i :指定打包程序使用的图标(icon)文件
-F:打包成可执行程序
-h:查看帮助
-p:添加使用的第三方库路径
-v:查看 PyInstaller 版本
-w:取消控制台显示(默认是显示控制台的)
eg:
pyinstaller -F -p C:\SystemLib\site-packages -p C:\MyLib main.py -i C:\image\excel.ico
解释:
打包 main.py 脚本
main.py包含第三方脚本,一个是系统脚本,一个是自定义脚本
设置可执行程序的图标为excel.ico

test python script

from tkinter import *


def btnClick():
    textLabel['text'] = '我点击了按钮'


root = Tk(className="测试打包");

textLabel = Label(root, text='提示显示', justify=LEFT, padx=10)
textLabel.pack(side=TOP)

btn = Button(root)
btn['text'] = '点击测试'
btn['command'] = btnClick
btn.pack(side=BOTTOM)

mainloop()

Linux

Compile python into so file for calling

1.安装cython,gcc
sudo apt install python3-dev gcc
2.安装cpython
pip3 install cython
3.将需要转化的python源文件,代码调用python文件,打包加密文件放在同一个目录中
4.在当前目录中执行
python3 setup.py build_ext
5.生成文件 /build/lib.linux-x86_64-3.6/t1.cpython-36m-x86_64-linux-gnu.so*
6.复制 /build/lib.linux-x86_64-3.6/t1.cpython-36m-x86_64-linux-gnu.so* 与
t3 处于同一文件夹
7.删除 t1.py rm t1.py
8.调用t3.py  python t3.py
9.正常输出t1.py 的内容

test python script

script 1 t1.py

Description: data script, that is, the source file that needs to be encrypted

import datetime

class Today():
    def get_time(self):
        print(datetime.datetime.now())
        
    def say(self):
        print("hello from JC!")

script 2 t2.py

Description: encrypted script

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize(["t1.py"]))

Script 3 t3.py

Definitions: A call to script t1 was made

from mytest import Today

t = Today()
t.get_time()
t.say()

call plan

Data docking ideas

1.python方,
	将核心代码加密为 .so 文件,通过外层函数处理和转换数据,转换后的数据,对加密脚本进行黑箱调用。
2.java方,
	定义python脚本路径,定义JSON数据对象格式,转换JSON数据为数据流,调用python暴露的外层壳函数,使用如下代码进行调用

Test calling code Java

@Component
public class AlgorithmExecuteHelper {

    private static final Logger logger = LoggerFactory.getLogger(AlgorithmExecuteHelper.class);

    private final String pythonPath;

    private final ThreadPoolTaskExecutor taskExecutor;

    public AlgorithmExecuteHelper(@Value("${python-path}") String pythonPath, ThreadPoolTaskExecutor taskExecutor) {
        this.pythonPath = pythonPath;
        this.taskExecutor = taskExecutor;
    }


    public ProcessResultDto execute( File directory,  File enterFile,  DataConsumer consumer){
        Process process = null;
        try {
            process = new ProcessBuilder()
                    .command(pythonPath, enterFile.getName())
                    .directory(directory)
                    .start();

            final BlockingQueue<String> inputQueue = new LinkedBlockingQueue<>();
            final BlockingQueue<String> errorQueue = new LinkedBlockingQueue<>();
            taskExecutor.execute(this.readStreamToQueue(new BufferedInputStream(process.getInputStream()), inputQueue));
            taskExecutor.execute(this.readStreamToQueue(new BufferedInputStream(process.getErrorStream()), errorQueue));

            try (final OutputStream outputStream = new BufferedOutputStream(new GZIPOutputStream(process.getOutputStream()))) {
                consumer.accept(outputStream);
            }

            return new ProcessResultDto(process.waitFor(), inputQueue, errorQueue);
        } catch (Exception e) {
            throw new RuntimeException();
        } finally {
            if (Objects.nonNull(process)) {
                process.destroy();
            }
        }
    }

    private Runnable readStreamToQueue( InputStream inputStream,  BlockingQueue<String> queue) {
        return () -> {
            String line;
            try (final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                while ((line = reader.readLine()) != null) {
                    queue.add(line);
                }
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
            }
        };
    }

    @FunctionalInterface
    public interface DataConsumer {
        void accept(OutputStream out) throws Exception;
    }

}

Test calling code Python

import sys
import gzip
import json

def getInputData():
    gzipByteArray = sys.stdin.buffer.read()
    jsonStr = gzip.decompress(gzipByteArray).decode("utf-8")
    return json.loads(jsonStr)

Guess you like

Origin blog.csdn.net/weixin_42559985/article/details/129987771