From 87bcb5df21a406372afc208d96dc48c75fe09999 Mon Sep 17 00:00:00 2001 From: chenjian Date: Tue, 3 Jan 2023 10:47:08 +0800 Subject: [PATCH 1/3] [Model] add style transfer model (#922) * add style transfer model * add examples for generation model * add unit test * add speed comparison * add speed comparison * add variable for constant * add preprocessor and postprocessor * add preprocessor and postprocessor * fix * fix according to review Co-authored-by: DefTruth <31974251+DefTruth@users.noreply.github.com> --- examples/vision/generation/anemigan/README.md | 36 +++++++ .../generation/anemigan/cpp/CMakeLists.txt | 13 +++ .../vision/generation/anemigan/cpp/README.md | 84 +++++++++++++++ .../vision/generation/anemigan/cpp/infer.cc | 69 ++++++++++++ .../generation/anemigan/python/README.md | 70 ++++++++++++ .../generation/anemigan/python/infer.py | 43 ++++++++ fastdeploy/vision.h | 1 + .../vision/generation/contrib/animegan.cc | 80 ++++++++++++++ .../vision/generation/contrib/animegan.h | 79 ++++++++++++++ .../generation/contrib/animegan_pybind.cc | 78 ++++++++++++++ .../generation/contrib/postprocessor.cc | 49 +++++++++ .../vision/generation/contrib/postprocessor.h | 43 ++++++++ .../vision/generation/contrib/preprocessor.cc | 63 +++++++++++ .../vision/generation/contrib/preprocessor.h | 42 ++++++++ .../vision/generation/generation_pybind.cc | 25 +++++ fastdeploy/vision/vision_pybind.cc | 2 + python/fastdeploy/vision/__init__.py | 1 + .../fastdeploy/vision/generation/__init__.py | 16 +++ .../vision/generation/contrib/__init__.py | 15 +++ .../vision/generation/contrib/anemigan.py | 102 ++++++++++++++++++ tests/models/test_animegan.py | 46 ++++++++ tests/models/test_basicvsr.py | 4 + tests/models/test_edvr.py | 6 +- 23 files changed, 966 insertions(+), 1 deletion(-) create mode 100644 examples/vision/generation/anemigan/README.md create mode 100755 examples/vision/generation/anemigan/cpp/CMakeLists.txt create mode 100755 examples/vision/generation/anemigan/cpp/README.md create mode 100644 examples/vision/generation/anemigan/cpp/infer.cc create mode 100644 examples/vision/generation/anemigan/python/README.md create mode 100644 examples/vision/generation/anemigan/python/infer.py create mode 100644 fastdeploy/vision/generation/contrib/animegan.cc create mode 100644 fastdeploy/vision/generation/contrib/animegan.h create mode 100644 fastdeploy/vision/generation/contrib/animegan_pybind.cc create mode 100644 fastdeploy/vision/generation/contrib/postprocessor.cc create mode 100644 fastdeploy/vision/generation/contrib/postprocessor.h create mode 100644 fastdeploy/vision/generation/contrib/preprocessor.cc create mode 100644 fastdeploy/vision/generation/contrib/preprocessor.h create mode 100644 fastdeploy/vision/generation/generation_pybind.cc create mode 100644 python/fastdeploy/vision/generation/__init__.py create mode 100644 python/fastdeploy/vision/generation/contrib/__init__.py create mode 100644 python/fastdeploy/vision/generation/contrib/anemigan.py create mode 100644 tests/models/test_animegan.py diff --git a/examples/vision/generation/anemigan/README.md b/examples/vision/generation/anemigan/README.md new file mode 100644 index 000000000..721ed5644 --- /dev/null +++ b/examples/vision/generation/anemigan/README.md @@ -0,0 +1,36 @@ +# 图像生成模型 + +FastDeploy目前支持PaddleHub预训练模型库中如下风格迁移模型的部署 + +| 模型 | 说明 | 模型格式 | +| :--- | :--- | :------- | +|[animegan_v1_hayao_60](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v1_hayao_60&en_category=GANs)|可将输入的图像转换成宫崎骏动漫风格,模型权重转换自AnimeGAN V1官方开源项目|paddle| +|[animegan_v2_paprika_97](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_paprika_97&en_category=GANs)|可将输入的图像转换成今敏红辣椒动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_hayao_64](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_hayao_64&en_category=GANs)|可将输入的图像转换成宫崎骏动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_shinkai_53](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_shinkai_53&en_category=GANs)|可将输入的图像转换成新海诚动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_shinkai_33](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_shinkai_33&en_category=GANs)|可将输入的图像转换成新海诚动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_paprika_54](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_paprika_54&en_category=GANs)|可将输入的图像转换成今敏红辣椒动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_hayao_99](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_hayao_99&en_category=GANs)|可将输入的图像转换成宫崎骏动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_paprika_74](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_paprika_74&en_category=GANs)|可将输入的图像转换成今敏红辣椒动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| +|[animegan_v2_paprika_98](https://www.paddlepaddle.org.cn/hubdetail?name=animegan_v2_paprika_98&en_category=GANs)|可将输入的图像转换成今敏红辣椒动漫风格,模型权重转换自AnimeGAN V2官方开源项目|paddle| + +## FastDeploy paddle backend部署和hub速度对比(ips, 越高越好) +| Device | FastDeploy | Hub | +| :--- | :--- | :------- | +| CPU | 0.075 | 0.069| +| GPU | 8.33 | 8.26 | + + + +## 下载预训练模型 +使用fastdeploy.download_model即可以下载模型, 例如下载animegan_v1_hayao_60 +```python +import fastdeploy as fd +fd.download_model(name='animegan_v1_hayao_60', path='./', format='paddle') +``` +将会在当前目录获得animegan_v1_hayao_60的预训练模型。 + +## 详细部署文档 + +- [Python部署](python) +- [C++部署](cpp) diff --git a/examples/vision/generation/anemigan/cpp/CMakeLists.txt b/examples/vision/generation/anemigan/cpp/CMakeLists.txt new file mode 100755 index 000000000..7d1bd2ee1 --- /dev/null +++ b/examples/vision/generation/anemigan/cpp/CMakeLists.txt @@ -0,0 +1,13 @@ +PROJECT(infer_demo C CXX) +CMAKE_MINIMUM_REQUIRED (VERSION 3.10) + +# 指定下载解压后的fastdeploy库路径 +option(FASTDEPLOY_INSTALL_DIR "Path of downloaded fastdeploy sdk.") +include(${FASTDEPLOY_INSTALL_DIR}/utils/gflags.cmake) +include(${FASTDEPLOY_INSTALL_DIR}/FastDeploy.cmake) + +# 添加FastDeploy依赖头文件 +include_directories(${FASTDEPLOY_INCS}) + +add_executable(infer_demo ${PROJECT_SOURCE_DIR}/infer.cc) +target_link_libraries(infer_demo ${FASTDEPLOY_LIBS} ${GFLAGS_LIBRARIES}) diff --git a/examples/vision/generation/anemigan/cpp/README.md b/examples/vision/generation/anemigan/cpp/README.md new file mode 100755 index 000000000..9d58c6ad3 --- /dev/null +++ b/examples/vision/generation/anemigan/cpp/README.md @@ -0,0 +1,84 @@ +# AnimeGAN C++部署示例 + +本目录下提供`infer.cc`快速完成AnimeGAN在CPU/GPU部署的示例。 + +在部署前,需确认以下两个步骤 + +- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md) +- 2. 根据开发环境,下载预编译部署库和samples代码,参考[FastDeploy预编译库](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md) + +以Linux上AnimeGAN推理为例,在本目录执行如下命令即可完成编译测试,支持此模型需保证FastDeploy版本1.0.2以上(x.x.x>=1.0.2) + +```bash +mkdir build +cd build +# 下载FastDeploy预编译库,用户可在上文提到的`FastDeploy预编译库`中自行选择合适的版本使用 +wget https://bj.bcebos.com/fastdeploy/release/cpp/fastdeploy-linux-x64-x.x.x.tgz +tar xvf fastdeploy-linux-x64-x.x.x.tgz +cmake .. -DFASTDEPLOY_INSTALL_DIR=${PWD}/fastdeploy-linux-x64-x.x.x +make -j + +# 下载准备好的模型文件和测试图片 +wget https://bj.bcebos.com/paddlehub/fastdeploy/style_transfer_testimg.jpg +wget https://bj.bcebos.com/paddlehub/fastdeploy/animegan_v1_hayao_60_v1.0.0.tgz +tar xvfz animegan_v1_hayao_60_v1.0.0.tgz + +# CPU推理 +./infer_demo --model animegan_v1_hayao_60 --image style_transfer_testimg.jpg --device cpu +# GPU推理 +./infer_demo --model animegan_v1_hayao_60 --image style_transfer_testimg.jpg --device gpu +``` + +以上命令只适用于Linux或MacOS, Windows下SDK的使用方式请参考: +- [如何在Windows中使用FastDeploy C++ SDK](../../../../../docs/cn/faq/use_sdk_on_windows.md) + +## AnimeGAN C++接口 + +### AnimeGAN类 + +```c++ +fastdeploy::vision::generation::AnimeGAN( + const string& model_file, + const string& params_file = "", + const RuntimeOption& runtime_option = RuntimeOption(), + const ModelFormat& model_format = ModelFormat::PADDLE) +``` + +AnimeGAN模型加载和初始化,其中model_file为导出的Paddle模型结构文件,params_file为模型参数文件。 + +**参数** + +> * **model_file**(str): 模型文件路径 +> * **params_file**(str): 参数文件路径 +> * **runtime_option**(RuntimeOption): 后端推理配置,默认为None,即采用默认配置 +> * **model_format**(ModelFormat): 模型格式,默认为Paddle格式 + +#### Predict函数 + +> ```c++ +> bool AnimeGAN::Predict(cv::Mat& image, cv::Mat* result) +> ``` +> +> 模型预测入口,输入图像输出风格迁移后的结果。 +> +> **参数** +> +> > * **image**: 输入数据,注意需为HWC,BGR格式 +> > * **result**: 风格转换后的图像,BGR格式 + +#### BatchPredict函数 + +> ```c++ +> bool AnimeGAN::BatchPredict(const std::vector& images, std::vector* results); +> ``` +> +> 模型预测入口,输入一组图像并输出风格迁移后的结果。 +> +> **参数** +> +> > * **images**: 输入数据,一组图像数据,注意需为HWC,BGR格式 +> > * **results**: 风格转换后的一组图像,BGR格式 + +- [模型介绍](../../) +- [Python部署](../python) +- [如何切换模型推理后端引擎](../../../../../docs/cn/faq/how_to_change_backend.md) diff --git a/examples/vision/generation/anemigan/cpp/infer.cc b/examples/vision/generation/anemigan/cpp/infer.cc new file mode 100644 index 000000000..ad10797e9 --- /dev/null +++ b/examples/vision/generation/anemigan/cpp/infer.cc @@ -0,0 +1,69 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/vision.h" +#include "gflags/gflags.h" + +DEFINE_string(model, "", "Directory of the inference model."); +DEFINE_string(image, "", "Path of the image file."); +DEFINE_string(device, "cpu", + "Type of inference device, support 'cpu' or 'gpu'."); + +void PrintUsage() { + std::cout << "Usage: infer_demo --model model_path --image img_path --device [cpu|gpu]" + << std::endl; + std::cout << "Default value of device: cpu" << std::endl; +} + +bool CreateRuntimeOption(fastdeploy::RuntimeOption* option) { + if (FLAGS_device == "gpu") { + option->UseGpu(); + } + else if (FLAGS_device == "cpu") { + option->SetPaddleMKLDNN(false); + return true; + } else { + std::cerr << "Only support device CPU/GPU now, " << FLAGS_device << " is not supported." << std::endl; + return false; + } + + return true; +} + +int main(int argc, char* argv[]) { + google::ParseCommandLineFlags(&argc, &argv, true); + auto option = fastdeploy::RuntimeOption(); + if (!CreateRuntimeOption(&option)) { + PrintUsage(); + return -1; + } + + auto model = fastdeploy::vision::generation::AnimeGAN(FLAGS_model+"/model.pdmodel", FLAGS_model+"/model.pdiparams", option); + if (!model.Initialized()) { + std::cerr << "Failed to initialize." << std::endl; + return -1; + } + + auto im = cv::imread(FLAGS_image); + cv::Mat res; + if (!model.Predict(im, &res)) { + std::cerr << "Failed to predict." << std::endl; + return -1; + } + + cv::imwrite("style_transfer_result.png", res); + std::cout << "Visualized result saved in ./style_transfer_result.png" << std::endl; + + return 0; +} diff --git a/examples/vision/generation/anemigan/python/README.md b/examples/vision/generation/anemigan/python/README.md new file mode 100644 index 000000000..9c4562402 --- /dev/null +++ b/examples/vision/generation/anemigan/python/README.md @@ -0,0 +1,70 @@ +# AnimeGAN Python部署示例 + +在部署前,需确认以下两个步骤 + +- 1. 软硬件环境满足要求,参考[FastDeploy环境要求](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md) +- 2. FastDeploy Python whl包安装,参考[FastDeploy Python安装](../../../../../docs/cn/build_and_install/download_prebuilt_libraries.md) + +本目录下提供`infer.py`快速完成AnimeGAN在CPU/GPU,以及GPU上通过TensorRT加速部署的示例。执行如下脚本即可完成 + +```bash +# 下载部署示例代码 +git clone https://github.com/PaddlePaddle/FastDeploy.git +cd FastDeploy/examples/vision/generation/anemigan/python +# 下载准备好的测试图片 +wget https://bj.bcebos.com/paddlehub/fastdeploy/style_transfer_testimg.jpg + +# CPU推理 +python infer.py --model animegan_v1_hayao_60 --image style_transfer_testimg.jpg --device cpu +# GPU推理 +python infer.py --model animegan_v1_hayao_60 --image style_transfer_testimg.jpg --device gpu +``` + +## AnimeGAN Python接口 + +```python +fd.vision.generation.AnimeGAN(model_file, params_file, runtime_option=None, model_format=ModelFormat.PADDLE) +``` + +AnimeGAN模型加载和初始化,其中model_file和params_file为用于Paddle inference的模型结构文件和参数文件。 + +**参数** + +> * **model_file**(str): 模型文件路径 +> * **params_file**(str): 参数文件路径 +> * **runtime_option**(RuntimeOption): 后端推理配置,默认为None,即采用默认配置 +> * **model_format**(ModelFormat): 模型格式,默认为Paddle格式 + + +### predict函数 + +> ```python +> AnimeGAN.predict(input_image) +> ``` +> +> 模型预测入口,输入图像输出风格迁移后的结果。 +> +> **参数** +> +> > * **input_image**(np.ndarray): 输入数据,注意需为HWC,BGR格式 + +> **返回** np.ndarray, 风格转换后的图像,BGR格式 + +### batch_predict函数 +> ```python +> AnimeGAN.batch_predict函数(input_images) +> ``` +> +> 模型预测入口,输入一组图像并输出风格迁移后的结果。 +> +> **参数** +> +> > * **input_images**(list(np.ndarray)): 输入数据,一组图像数据,注意需为HWC,BGR格式 + +> **返回** list(np.ndarray), 风格转换后的一组图像,BGR格式 + +## 其它文档 + +- [风格迁移 模型介绍](..) +- [C++部署](../cpp) +- [如何切换模型推理后端引擎](../../../../../docs/cn/faq/how_to_change_backend.md) diff --git a/examples/vision/generation/anemigan/python/infer.py b/examples/vision/generation/anemigan/python/infer.py new file mode 100644 index 000000000..69f610eda --- /dev/null +++ b/examples/vision/generation/anemigan/python/infer.py @@ -0,0 +1,43 @@ +import cv2 +import os +import fastdeploy as fd + + +def parse_arguments(): + import argparse + import ast + parser = argparse.ArgumentParser() + parser.add_argument("--model", required=True, help="Name of the model.") + parser.add_argument( + "--image", type=str, required=True, help="Path of test image file.") + parser.add_argument( + "--device", + type=str, + default='cpu', + help="Type of inference device, support 'cpu' or 'gpu'.") + return parser.parse_args() + + +def build_option(args): + option = fd.RuntimeOption() + if args.device.lower() == "gpu": + option.use_gpu() + else: + option.set_paddle_mkldnn(False) + return option + + +args = parse_arguments() + +# 配置runtime,加载模型 +runtime_option = build_option(args) +fd.download_model(name=args.model, path='./', format='paddle') +model_file = os.path.join(args.model, "model.pdmodel") +params_file = os.path.join(args.model, "model.pdiparams") +model = fd.vision.generation.AnimeGAN( + model_file, params_file, runtime_option=runtime_option) + +# 预测图片并保存结果 +im = cv2.imread(args.image) +result = model.predict(im) +cv2.imwrite('style_transfer_result.png', result) diff --git a/fastdeploy/vision.h b/fastdeploy/vision.h index ef2fc90a6..0714a9766 100644 --- a/fastdeploy/vision.h +++ b/fastdeploy/vision.h @@ -55,6 +55,7 @@ #include "fastdeploy/vision/segmentation/ppseg/model.h" #include "fastdeploy/vision/sr/ppsr/model.h" #include "fastdeploy/vision/tracking/pptracking/model.h" +#include "fastdeploy/vision/generation/contrib/animegan.h" #endif diff --git a/fastdeploy/vision/generation/contrib/animegan.cc b/fastdeploy/vision/generation/contrib/animegan.cc new file mode 100644 index 000000000..22962daa1 --- /dev/null +++ b/fastdeploy/vision/generation/contrib/animegan.cc @@ -0,0 +1,80 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/vision/generation/contrib/animegan.h" +#include "fastdeploy/function/functions.h" + +namespace fastdeploy { +namespace vision { +namespace generation { + +AnimeGAN::AnimeGAN(const std::string& model_file, const std::string& params_file, + const RuntimeOption& custom_option, + const ModelFormat& model_format) { + + valid_cpu_backends = {Backend::PDINFER}; + valid_gpu_backends = {Backend::PDINFER}; + + runtime_option = custom_option; + runtime_option.model_format = model_format; + runtime_option.model_file = model_file; + runtime_option.params_file = params_file; + + initialized = Initialize(); +} + +bool AnimeGAN::Initialize() { + if (!InitRuntime()) { + FDERROR << "Failed to initialize fastdeploy backend." << std::endl; + return false; + } + return true; +} + + +bool AnimeGAN::Predict(cv::Mat& img, cv::Mat* result) { + std::vector results; + if (!BatchPredict({img}, &results)) { + return false; + } + *result = std::move(results[0]); + return true; +} + +bool AnimeGAN::BatchPredict(const std::vector& images, std::vector* results) { + std::vector fd_images = WrapMat(images); + std::vector processed_data(1); + if (!preprocessor_.Run(fd_images, &(processed_data))) { + FDERROR << "Failed to preprocess input data while using model:" + << ModelName() << "." << std::endl; + return false; + } + std::vector infer_result(1); + processed_data[0].name = InputInfoOfRuntime(0).name; + + if (!Infer(processed_data, &infer_result)) { + FDERROR << "Failed to inference by runtime." << std::endl; + return false; + } + if (!postprocessor_.Run(infer_result, results)) { + FDERROR << "Failed to postprocess while using model:" << ModelName() << "." + << std::endl; + return false; + } + return true; +} + +} // namespace generation +} // namespace vision +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/vision/generation/contrib/animegan.h b/fastdeploy/vision/generation/contrib/animegan.h new file mode 100644 index 000000000..9d1f9aa27 --- /dev/null +++ b/fastdeploy/vision/generation/contrib/animegan.h @@ -0,0 +1,79 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "fastdeploy/fastdeploy_model.h" +#include "fastdeploy/vision/common/processors/transform.h" +#include "fastdeploy/vision/generation/contrib/preprocessor.h" +#include "fastdeploy/vision/generation/contrib/postprocessor.h" + +namespace fastdeploy { + +namespace vision { + +namespace generation { +/*! @brief AnimeGAN model object is used when load a AnimeGAN model. + */ +class FASTDEPLOY_DECL AnimeGAN : public FastDeployModel { + public: + /** \brief Set path of model file and the configuration of runtime. + * + * \param[in] model_file Path of model file, e.g ./model.pdmodel + * \param[in] params_file Path of parameter file, e.g ./model.pdiparams, if the model format is ONNX, this parameter will be ignored + * \param[in] custom_option RuntimeOption for inference, the default will use cpu, and choose the backend defined in "valid_cpu_backends" + * \param[in] model_format Model format of the loaded model, default is PADDLE format + */ + AnimeGAN(const std::string& model_file, const std::string& params_file = "", + const RuntimeOption& custom_option = RuntimeOption(), + const ModelFormat& model_format = ModelFormat::PADDLE); + + std::string ModelName() const { return "styletransfer/animegan"; } + + /** \brief Predict the style transfer result for an input image + * + * \param[in] im The input image data, comes from cv::imread(), is a 3-D array with layout HWC, BGR format + * \param[in] result The output style transfer result will be writen to this structure + * \return true if the prediction successed, otherwise false + */ + bool Predict(cv::Mat& img, cv::Mat* result); + + /** \brief Predict the style transfer result for a batch of input images + * + * \param[in] images The list of input images, each element comes from cv::imread(), is a 3-D array with layout HWC, BGR format + * \param[in] results The list of output style transfer results will be writen to this structure + * \return true if the batch prediction successed, otherwise false + */ + bool BatchPredict(const std::vector& images, + std::vector* results); + + // Get preprocessor reference of AnimeGAN + AnimeGANPreprocessor& GetPreprocessor() { + return preprocessor_; + } + + // Get postprocessor reference of AnimeGAN + AnimeGANPostprocessor& GetPostprocessor() { + return postprocessor_; + } + + private: + bool Initialize(); + + AnimeGANPreprocessor preprocessor_; + AnimeGANPostprocessor postprocessor_; +}; + +} // namespace generation +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/generation/contrib/animegan_pybind.cc b/fastdeploy/vision/generation/contrib/animegan_pybind.cc new file mode 100644 index 000000000..853069d71 --- /dev/null +++ b/fastdeploy/vision/generation/contrib/animegan_pybind.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/pybind/main.h" + +namespace fastdeploy { +void BindAnimeGAN(pybind11::module& m) { + pybind11::class_(m, "AnimeGAN") + .def(pybind11::init()) + .def("predict", + [](vision::generation::AnimeGAN& self, pybind11::array& data) { + auto mat = PyArrayToCvMat(data); + cv::Mat res; + self.Predict(mat, &res); + auto ret = pybind11::array_t( + {res.rows, res.cols, res.channels()}, res.data); + return ret; + }) + .def("batch_predict", + [](vision::generation::AnimeGAN& self, std::vector& data) { + std::vector images; + for (size_t i = 0; i < data.size(); ++i) { + images.push_back(PyArrayToCvMat(data[i])); + } + std::vector results; + self.BatchPredict(images, &results); + std::vector> ret; + for(size_t i = 0; i < results.size(); ++i){ + ret.push_back(pybind11::array_t( + {results[i].rows, results[i].cols, results[i].channels()}, results[i].data)); + } + return ret; + }) + .def_property_readonly("preprocessor", &vision::generation::AnimeGAN::GetPreprocessor) + .def_property_readonly("postprocessor", &vision::generation::AnimeGAN::GetPostprocessor); + + pybind11::class_( + m, "AnimeGANPreprocessor") + .def(pybind11::init<>()) + .def("run", [](vision::generation::AnimeGANPreprocessor& self, std::vector& im_list) { + std::vector images; + for (size_t i = 0; i < im_list.size(); ++i) { + images.push_back(vision::WrapMat(PyArrayToCvMat(im_list[i]))); + } + std::vector outputs; + if (!self.Run(images, &outputs)) { + throw std::runtime_error("Failed to preprocess the input data in PaddleClasPreprocessor."); + } + for (size_t i = 0; i < outputs.size(); ++i) { + outputs[i].StopSharing(); + } + return outputs; + }); + pybind11::class_( + m, "AnimeGANPostprocessor") + .def(pybind11::init<>()) + .def("run", [](vision::generation::AnimeGANPostprocessor& self, std::vector& inputs) { + std::vector results; + if (!self.Run(inputs, &results)) { + throw std::runtime_error("Failed to postprocess the runtime result in YOLOv5Postprocessor."); + } + return results; + }); + +} +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/vision/generation/contrib/postprocessor.cc b/fastdeploy/vision/generation/contrib/postprocessor.cc new file mode 100644 index 000000000..68dbaf8f3 --- /dev/null +++ b/fastdeploy/vision/generation/contrib/postprocessor.cc @@ -0,0 +1,49 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/vision/generation/contrib/postprocessor.h" + +namespace fastdeploy { +namespace vision { +namespace generation { + +bool AnimeGANPostprocessor::Run(std::vector& infer_results, + std::vector* results) { + // 1. Reverse normalization + // 2. RGB2BGR + FDTensor& output_tensor = infer_results.at(0); + std::vector shape = output_tensor.Shape(); // n, h, w, c + int size = shape[1] * shape[2] * shape[3]; + results->resize(shape[0]); + float* infer_result_data = reinterpret_cast(output_tensor.Data()); + for(size_t i = 0; i < results->size(); ++i){ + Mat result_mat = Mat::Create(shape[1], shape[2], 3, FDDataType::FP32, infer_result_data+i*size); + std::vector mean{127.5f, 127.5f, 127.5f}; + std::vector std{127.5f, 127.5f, 127.5f}; + Convert::Run(&result_mat, mean, std); + // tmp data type is float[0-1.0],convert to uint type + auto temp = result_mat.GetOpenCVMat(); + cv::Mat res = cv::Mat::zeros(temp->size(), CV_8UC3); + temp->convertTo(res, CV_8UC3, 1); + Mat fd_image = WrapMat(res); + BGR2RGB::Run(&fd_image); + res = *(fd_image.GetOpenCVMat()); + res.copyTo(results->at(i)); + } + return true; +} + +} // namespace generation +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/generation/contrib/postprocessor.h b/fastdeploy/vision/generation/contrib/postprocessor.h new file mode 100644 index 000000000..3f3a7728b --- /dev/null +++ b/fastdeploy/vision/generation/contrib/postprocessor.h @@ -0,0 +1,43 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "fastdeploy/vision/common/processors/transform.h" +#include "fastdeploy/function/functions.h" + +namespace fastdeploy { +namespace vision { + +namespace generation { +/*! @brief Postprocessor object for AnimeGAN serials model. + */ +class FASTDEPLOY_DECL AnimeGANPostprocessor { + public: + /** \brief Create a postprocessor instance for AnimeGAN serials model + */ + AnimeGANPostprocessor() {} + + /** \brief Process the result of runtime + * + * \param[in] infer_results The inference results from runtime + * \param[in] results The output results of style transfer + * \return true if the postprocess successed, otherwise false + */ + bool Run(std::vector& infer_results, + std::vector* results); +}; + +} // namespace generation +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/generation/contrib/preprocessor.cc b/fastdeploy/vision/generation/contrib/preprocessor.cc new file mode 100644 index 000000000..24e75fdc3 --- /dev/null +++ b/fastdeploy/vision/generation/contrib/preprocessor.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/vision/generation/contrib/preprocessor.h" + +namespace fastdeploy { +namespace vision { +namespace generation { + +bool AnimeGANPreprocessor::Run(std::vector& images, std::vector* outputs) { + // 1. BGR2RGB + // 2. Convert(opencv style) or Normalize + for (size_t i = 0; i < images.size(); ++i) { + auto ret = BGR2RGB::Run(&images[i]); + if (!ret) { + FDERROR << "Failed to processs image:" << i << " in " + << "BGR2RGB" << "." << std::endl; + return false; + } + ret = Cast::Run(&images[i], "float"); + if (!ret) { + FDERROR << "Failed to processs image:" << i << " in " + << "Cast" << "." << std::endl; + return false; + } + std::vector mean{1.f / 127.5f, 1.f / 127.5f, 1.f / 127.5f}; + std::vector std {-1.f, -1.f, -1.f}; + ret = Convert::Run(&images[i], mean, std); + if (!ret) { + FDERROR << "Failed to processs image:" << i << " in " + << "Cast" << "." << std::endl; + return false; + } + } + outputs->resize(1); + // Concat all the preprocessed data to a batch tensor + std::vector tensors(images.size()); + for (size_t i = 0; i < images.size(); ++i) { + images[i].ShareWithTensor(&(tensors[i])); + tensors[i].ExpandDim(0); + } + if (tensors.size() == 1) { + (*outputs)[0] = std::move(tensors[0]); + } else { + function::Concat(tensors, &((*outputs)[0]), 0); + } + return true; +} + +} // namespace generation +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/generation/contrib/preprocessor.h b/fastdeploy/vision/generation/contrib/preprocessor.h new file mode 100644 index 000000000..4fcf94a15 --- /dev/null +++ b/fastdeploy/vision/generation/contrib/preprocessor.h @@ -0,0 +1,42 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include "fastdeploy/vision/common/processors/transform.h" +#include "fastdeploy/function/functions.h" + +namespace fastdeploy { +namespace vision { + +namespace generation { +/*! @brief Preprocessor object for AnimeGAN serials model. + */ +class FASTDEPLOY_DECL AnimeGANPreprocessor { + public: + /** \brief Create a preprocessor instance for AnimeGAN serials model + */ + AnimeGANPreprocessor() {} + + /** \brief Process the input image and prepare input tensors for runtime + * + * \param[in] images The input image data list, all the elements are returned wrapped by FDMat. + * \param[in] output The output tensors which will feed in runtime + * \return true if the preprocess successed, otherwise false + */ + bool Run(std::vector& images, std::vector* output); +}; + +} // namespace generation +} // namespace vision +} // namespace fastdeploy diff --git a/fastdeploy/vision/generation/generation_pybind.cc b/fastdeploy/vision/generation/generation_pybind.cc new file mode 100644 index 000000000..d4f02612e --- /dev/null +++ b/fastdeploy/vision/generation/generation_pybind.cc @@ -0,0 +1,25 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/pybind/main.h" + +namespace fastdeploy { + +void BindAnimeGAN(pybind11::module& m); + +void BindGeneration(pybind11::module& m) { + auto generation_module = m.def_submodule("generation", "image generation submodule"); + BindAnimeGAN(generation_module); +} +} // namespace fastdeploy diff --git a/fastdeploy/vision/vision_pybind.cc b/fastdeploy/vision/vision_pybind.cc index cecd4f7c3..aa387b430 100644 --- a/fastdeploy/vision/vision_pybind.cc +++ b/fastdeploy/vision/vision_pybind.cc @@ -28,6 +28,7 @@ void BindTracking(pybind11::module& m); void BindKeyPointDetection(pybind11::module& m); void BindHeadPose(pybind11::module& m); void BindSR(pybind11::module& m); +void BindGeneration(pybind11::module& m); #ifdef ENABLE_VISION_VISUALIZE void BindVisualize(pybind11::module& m); #endif @@ -213,6 +214,7 @@ void BindVision(pybind11::module& m) { BindKeyPointDetection(m); BindHeadPose(m); BindSR(m); + BindGeneration(m); #ifdef ENABLE_VISION_VISUALIZE BindVisualize(m); #endif diff --git a/python/fastdeploy/vision/__init__.py b/python/fastdeploy/vision/__init__.py index a5531a8a9..ba9a2d0ca 100755 --- a/python/fastdeploy/vision/__init__.py +++ b/python/fastdeploy/vision/__init__.py @@ -26,6 +26,7 @@ from . import ocr from . import headpose from . import sr from . import evaluation +from . import generation from .utils import fd_result_to_json from .visualize import * from .. import C diff --git a/python/fastdeploy/vision/generation/__init__.py b/python/fastdeploy/vision/generation/__init__.py new file mode 100644 index 000000000..f568ed84d --- /dev/null +++ b/python/fastdeploy/vision/generation/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import +from .contrib.anemigan import AnimeGAN diff --git a/python/fastdeploy/vision/generation/contrib/__init__.py b/python/fastdeploy/vision/generation/contrib/__init__.py new file mode 100644 index 000000000..8034e10bf --- /dev/null +++ b/python/fastdeploy/vision/generation/contrib/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import diff --git a/python/fastdeploy/vision/generation/contrib/anemigan.py b/python/fastdeploy/vision/generation/contrib/anemigan.py new file mode 100644 index 000000000..eaed21c5e --- /dev/null +++ b/python/fastdeploy/vision/generation/contrib/anemigan.py @@ -0,0 +1,102 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import +import logging +from .... import FastDeployModel, ModelFormat +from .... import c_lib_wrap as C + + +class AnimeGANPreprocessor: + def __init__(self, config_file): + """Create a preprocessor for AnimeGAN. + """ + self._preprocessor = C.vision.generation.AnimeGANPreprocessor() + + def run(self, input_ims): + """Preprocess input images for AnimeGAN. + + :param: input_ims: (list of numpy.ndarray)The input image + :return: list of FDTensor + """ + return self._preprocessor.run(input_ims) + + +class AnimeGANPostprocessor: + def __init__(self): + """Create a postprocessor for AnimeGAN. + """ + self._postprocessor = C.vision.generation.AnimeGANPostprocessor() + + def run(self, runtime_results): + """Postprocess the runtime results for AnimeGAN + + :param: runtime_results: (list of FDTensor)The output FDTensor results from runtime + :return: results: (list) Final results + """ + return self._postprocessor.run(runtime_results) + + +class AnimeGAN(FastDeployModel): + def __init__(self, + model_file, + params_file="", + runtime_option=None, + model_format=ModelFormat.PADDLE): + """Load a AnimeGAN model. + + :param model_file: (str)Path of model file, e.g ./model.pdmodel + :param params_file: (str)Path of parameters file, e.g ./model.pdiparams, if the model_fomat is ModelFormat.ONNX, this param will be ignored, can be set as empty string + :param runtime_option: (fastdeploy.RuntimeOption)RuntimeOption for inference this model, if it's None, will use the default backend on CPU + :param model_format: (fastdeploy.ModelForamt)Model format of the loaded model + """ + # call super constructor to initialize self._runtime_option + super(AnimeGAN, self).__init__(runtime_option) + + self._model = C.vision.generation.AnimeGAN( + model_file, params_file, self._runtime_option, model_format) + # assert self.initialized to confirm initialization successfully. + assert self.initialized, "AnimeGAN initialize failed." + + def predict(self, input_image): + """ Predict the style transfer result for an input image + + :param input_image: (numpy.ndarray)The input image data, 3-D array with layout HWC, BGR format + :return: style transfer result + """ + return self._model.predict(input_image) + + def batch_predict(self, input_images): + """ Predict the style transfer result for multiple input images + + :param input_images: (list of numpy.ndarray)The list of input image data, each image is a 3-D array with layout HWC, BGR format + :return: a list of style transfer results + """ + return self._model.batch_predict(input_images) + + @property + def preprocessor(self): + """Get AnimeGANPreprocessor object of the loaded model + + :return AnimeGANPreprocessor + """ + return self._model.preprocessor + + @property + def postprocessor(self): + """Get AnimeGANPostprocessor object of the loaded model + + :return AnimeGANPostprocessor + """ + return self._model.postprocessor diff --git a/tests/models/test_animegan.py b/tests/models/test_animegan.py new file mode 100644 index 000000000..d698b05a8 --- /dev/null +++ b/tests/models/test_animegan.py @@ -0,0 +1,46 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import fastdeploy as fd +import cv2 +import os +import numpy as np + + +def test_animegan(): + model_name = 'animegan_v1_hayao_60' + model_path = fd.download_model( + name=model_name, path='./resources', format='paddle') + test_img = 'https://bj.bcebos.com/paddlehub/fastdeploy/style_transfer_testimg.jpg' + label_img = 'https://bj.bcebos.com/paddlehub/fastdeploy/style_transfer_result.png' + fd.download(test_img, "./resources") + fd.download(label_img, "./resources") + # use default backend + runtime_option = fd.RuntimeOption() + runtime_option.set_paddle_mkldnn(False) + model_file = os.path.join(model_path, "model.pdmodel") + params_file = os.path.join(model_path, "model.pdiparams") + animegan = fd.vision.generation.AnimeGAN( + model_file, params_file, runtime_option=runtime_option) + + src_img = cv2.imread("./resources/style_transfer_testimg.jpg") + label_img = cv2.imread("./resources/style_transfer_result.png") + res = animegan.predict(src_img) + + diff = np.fabs(res.astype(np.float32) - label_img.astype(np.float32)) / 255 + assert diff.max() < 1e-04, "There's diff in prediction." + + +if __name__ == "__main__": + test_animegan() diff --git a/tests/models/test_basicvsr.py b/tests/models/test_basicvsr.py index 479343444..9aeabc509 100644 --- a/tests/models/test_basicvsr.py +++ b/tests/models/test_basicvsr.py @@ -69,3 +69,7 @@ def test_basicvsr(): if t >= 10: break capture.release() + + +if __name__ == "__main__": + test_basicvsr() diff --git a/tests/models/test_edvr.py b/tests/models/test_edvr.py index a9f9517e7..a874c7d3b 100644 --- a/tests/models/test_edvr.py +++ b/tests/models/test_edvr.py @@ -1,4 +1,4 @@ -test_pptracking.py # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -74,3 +74,7 @@ def test_edvr(): if t >= 10: break capture.release() + + +if __name__ == "__main__": + test_edvr() From 11ce2f42a7231e6364b9bad10d5266253d343dfa Mon Sep 17 00:00:00 2001 From: heliqi <1101791222@qq.com> Date: Tue, 3 Jan 2023 13:17:38 +0800 Subject: [PATCH 2/3] [Serving]Update ppyoloe_runtime_config.pbtxt name (#1029) Update ppyoloe_runtime_config.pbtxt --- .../serving/models/runtime/ppyoloe_runtime_config.pbtxt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/vision/detection/paddledetection/serving/models/runtime/ppyoloe_runtime_config.pbtxt b/examples/vision/detection/paddledetection/serving/models/runtime/ppyoloe_runtime_config.pbtxt index 39b2c6045..dc8d15845 100644 --- a/examples/vision/detection/paddledetection/serving/models/runtime/ppyoloe_runtime_config.pbtxt +++ b/examples/vision/detection/paddledetection/serving/models/runtime/ppyoloe_runtime_config.pbtxt @@ -1,5 +1,5 @@ # optional, If name is specified it must match the name of the model repository directory containing the model. -name: "ppyoloe_runtime" +name: "runtime" backend: "fastdeploy" # Input configuration of the model From ab49b41080a3442744e10e5000408ab6d6410a19 Mon Sep 17 00:00:00 2001 From: Thomas Young <35565423+HexToString@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:57:03 +0800 Subject: [PATCH 3/3] add encryption (#1002) * add encryption * add doc * add doc * fix bug --- CMakeLists.txt | 18 +- FastDeploy.cmake.in | 2 + cmake/openssl.cmake | 50 ++++ cmake/summary.cmake | 1 + fastdeploy/encryption.h | 20 ++ fastdeploy/encryption/encryption_pybind.cc | 30 +++ fastdeploy/encryption/include/decrypt.h | 60 +++++ fastdeploy/encryption/include/encrypt.h | 58 +++++ fastdeploy/encryption/include/model_code.h | 43 ++++ fastdeploy/encryption/src/decrypt.cc | 109 +++++++++ fastdeploy/encryption/src/encrypt.cc | 104 ++++++++ .../util/include/constant/constant_model.h | 30 +++ .../encryption/util/include/crypto/aes_gcm.h | 130 ++++++++++ .../encryption/util/include/crypto/base64.h | 33 +++ .../encryption/util/include/crypto/basic.h | 78 ++++++ .../util/include/crypto/sha256_utils.h | 40 ++++ fastdeploy/encryption/util/include/io_utils.h | 53 +++++ fastdeploy/encryption/util/include/log.h | 24 ++ .../encryption/util/include/system_utils.h | 42 ++++ .../encryption/util/src/crypto/aes_gcm.cc | 193 +++++++++++++++ .../encryption/util/src/crypto/base64.cc | 133 +++++++++++ .../encryption/util/src/crypto/basic.cc | 81 +++++++ .../util/src/crypto/sha256_utils.cc | 85 +++++++ fastdeploy/encryption/util/src/io_utils.cc | 225 ++++++++++++++++++ .../encryption/util/src/system_utils.cc | 144 +++++++++++ fastdeploy/pybind/main.cc.in | 8 + fastdeploy/pybind/main.h | 4 + python/fastdeploy/__init__.py | 1 + python/fastdeploy/encryption/__init__.py | 16 ++ python/fastdeploy/encryption/encryption.py | 41 ++++ python/setup.py | 1 + tests/models/test_encryption.py | 9 + 32 files changed, 1865 insertions(+), 1 deletion(-) create mode 100755 cmake/openssl.cmake create mode 100755 fastdeploy/encryption.h create mode 100755 fastdeploy/encryption/encryption_pybind.cc create mode 100755 fastdeploy/encryption/include/decrypt.h create mode 100755 fastdeploy/encryption/include/encrypt.h create mode 100755 fastdeploy/encryption/include/model_code.h create mode 100755 fastdeploy/encryption/src/decrypt.cc create mode 100755 fastdeploy/encryption/src/encrypt.cc create mode 100755 fastdeploy/encryption/util/include/constant/constant_model.h create mode 100755 fastdeploy/encryption/util/include/crypto/aes_gcm.h create mode 100755 fastdeploy/encryption/util/include/crypto/base64.h create mode 100755 fastdeploy/encryption/util/include/crypto/basic.h create mode 100755 fastdeploy/encryption/util/include/crypto/sha256_utils.h create mode 100755 fastdeploy/encryption/util/include/io_utils.h create mode 100755 fastdeploy/encryption/util/include/log.h create mode 100755 fastdeploy/encryption/util/include/system_utils.h create mode 100755 fastdeploy/encryption/util/src/crypto/aes_gcm.cc create mode 100755 fastdeploy/encryption/util/src/crypto/base64.cc create mode 100755 fastdeploy/encryption/util/src/crypto/basic.cc create mode 100755 fastdeploy/encryption/util/src/crypto/sha256_utils.cc create mode 100755 fastdeploy/encryption/util/src/io_utils.cc create mode 100755 fastdeploy/encryption/util/src/system_utils.cc mode change 100644 => 100755 fastdeploy/pybind/main.cc.in mode change 100644 => 100755 fastdeploy/pybind/main.h mode change 100644 => 100755 python/fastdeploy/__init__.py create mode 100755 python/fastdeploy/encryption/__init__.py create mode 100755 python/fastdeploy/encryption/encryption.py create mode 100755 tests/models/test_encryption.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 44ff6c786..d4fe36fa3 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ option(ENABLE_LITE_BACKEND "Whether to enable paddle lite backend." OFF) option(ENABLE_VISION "Whether to enable vision models usage." OFF) option(ENABLE_TEXT "Whether to enable text models usage." OFF) option(ENABLE_FLYCV "Whether to enable flycv to boost image preprocess." OFF) +option(ENABLE_ENCRYPTION "Whether to enable ENCRYPTION." OFF) option(WITH_ASCEND "Whether to compile for Huawei Ascend deploy." OFF) option(WITH_TIMVX "Whether to compile for TIMVX deploy." OFF) option(WITH_KUNLUNXIN "Whether to compile for KunlunXin XPU deploy." OFF) @@ -195,11 +196,13 @@ file(GLOB_RECURSE DEPLOY_OPENVINO_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/f file(GLOB_RECURSE DEPLOY_RKNPU2_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/backends/rknpu/rknpu2/*.cc) file(GLOB_RECURSE DEPLOY_LITE_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/backends/lite/*.cc) file(GLOB_RECURSE DEPLOY_VISION_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/vision/*.cc) +file(GLOB_RECURSE DEPLOY_ENCRYPTION_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/encryption/*.cc) file(GLOB_RECURSE DEPLOY_PIPELINE_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/pipeline/*.cc) file(GLOB_RECURSE DEPLOY_VISION_CUDA_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/vision/*.cu) file(GLOB_RECURSE DEPLOY_TEXT_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/text/*.cc) file(GLOB_RECURSE DEPLOY_PYBIND_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/pybind/*.cc ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/*_pybind.cc) -list(REMOVE_ITEM ALL_DEPLOY_SRCS ${DEPLOY_ORT_SRCS} ${DEPLOY_PADDLE_SRCS} ${DEPLOY_POROS_SRCS} ${DEPLOY_TRT_SRCS} ${DEPLOY_OPENVINO_SRCS} ${DEPLOY_LITE_SRCS} ${DEPLOY_VISION_SRCS} ${DEPLOY_TEXT_SRCS} ${DEPLOY_PIPELINE_SRCS} ${DEPLOY_RKNPU2_SRCS}) + +list(REMOVE_ITEM ALL_DEPLOY_SRCS ${DEPLOY_ORT_SRCS} ${DEPLOY_PADDLE_SRCS} ${DEPLOY_POROS_SRCS} ${DEPLOY_TRT_SRCS} ${DEPLOY_OPENVINO_SRCS} ${DEPLOY_LITE_SRCS} ${DEPLOY_VISION_SRCS} ${DEPLOY_TEXT_SRCS} ${DEPLOY_PIPELINE_SRCS} ${DEPLOY_RKNPU2_SRCS} ${DEPLOY_ENCRYPTION_SRCS}) set(DEPEND_LIBS "") @@ -441,6 +444,14 @@ if(ENABLE_TEXT) include(${PROJECT_SOURCE_DIR}/cmake/fast_tokenizer.cmake) endif() +if(ENABLE_ENCRYPTION) + add_definitions(-DENABLE_ENCRYPTION) + list(APPEND ALL_DEPLOY_SRCS ${DEPLOY_ENCRYPTION_SRCS}) + include(${PROJECT_SOURCE_DIR}/cmake/gflags.cmake) + include(${PROJECT_SOURCE_DIR}/cmake/openssl.cmake) + list(APPEND DEPEND_LIBS ${OPENSSL_LIBRARIES}) +endif() + if(ENABLE_PADDLE_FRONTEND) add_definitions(-DENABLE_PADDLE_FRONTEND) include(${PROJECT_SOURCE_DIR}/cmake/paddle2onnx.cmake) @@ -653,6 +664,11 @@ if(BUILD_FASTDEPLOY_PYTHON) list(REMOVE_ITEM DEPLOY_PYBIND_SRCS ${VISION_PYBIND_SRCS} ${PIPELINE_PYBIND_SRCS}) endif() + if(NOT ENABLE_ENCRYPTION) + file(GLOB_RECURSE ENCRYPTION_PYBIND_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/encryption/*_pybind.cc) + list(REMOVE_ITEM DEPLOY_PYBIND_SRCS ${ENCRYPTION_PYBIND_SRCS}) + endif() + if (NOT ENABLE_TEXT) file(GLOB_RECURSE TEXT_PYBIND_SRCS ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/text/*_pybind.cc) list(REMOVE_ITEM DEPLOY_PYBIND_SRCS ${TEXT_PYBIND_SRCS}) diff --git a/FastDeploy.cmake.in b/FastDeploy.cmake.in index 83114e901..812caae54 100755 --- a/FastDeploy.cmake.in +++ b/FastDeploy.cmake.in @@ -13,6 +13,7 @@ set(ENABLE_PADDLE_FRONTEND @ENABLE_PADDLE_FRONTEND@) set(ENABLE_VISION @ENABLE_VISION@) set(ENABLE_FLYCV @ENABLE_FLYCV@) set(ENABLE_TEXT @ENABLE_TEXT@) +set(ENABLE_ENCRYPTION @ENABLE_ENCRYPTION@) set(BUILD_ON_JETSON @BUILD_ON_JETSON@) set(PADDLEINFERENCE_VERSION @PADDLEINFERENCE_VERSION@) set(OPENVINO_VERSION @OPENVINO_VERSION@) @@ -287,6 +288,7 @@ endif() message(STATUS " ENABLE_TRT_BACKEND : ${ENABLE_TRT_BACKEND}") message(STATUS " ENABLE_VISION : ${ENABLE_VISION}") message(STATUS " ENABLE_TEXT : ${ENABLE_TEXT}") +message(STATUS " ENABLE_ENCRYPTION : ${ENABLE_ENCRYPTION}") if(WITH_GPU) message(STATUS " CUDA_DIRECTORY : ${CUDA_DIRECTORY}") endif() diff --git a/cmake/openssl.cmake b/cmake/openssl.cmake new file mode 100755 index 000000000..2d7eb4402 --- /dev/null +++ b/cmake/openssl.cmake @@ -0,0 +1,50 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +SET(OPENSSL_URL_PREFIX "https://bj.bcebos.com/paddlex/tools") +IF(CMAKE_SYSTEM_NAME MATCHES "Windows") + set(OPENSSL_FILENAME "windows_openssl-1.1.0k") + set(COMPRESSED_SUFFIX ".zip") + add_definitions(-DWIN32) +ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(OPENSSL_FILENAME "openssl-1.1.0k") + set(COMPRESSED_SUFFIX ".tar.gz") + add_definitions(-DLINUX) +ENDIF() +set(OPENSSL_URL ${OPENSSL_URL_PREFIX}/${OPENSSL_FILENAME}${COMPRESSED_SUFFIX}) +if(THIRD_PARTY_PATH) + SET(OPENSSL_INSTALL_DIR ${THIRD_PARTY_PATH}) + SET(OPENSSL_ROOT_DIR ${THIRD_PARTY_PATH}/openssl-1.1.0k/install-${CMAKE_SYSTEM_PROCESSOR}) +else() + SET(OPENSSL_INSTALL_DIR ${FASTDEPLOY_INSTALL_DIR}/installed_fastdeploy/cmake) + SET(OPENSSL_ROOT_DIR ${FASTDEPLOY_INSTALL_DIR}/installed_fastdeploy/cmake/openssl-1.1.0k/install-${CMAKE_SYSTEM_PROCESSOR}) +endif() +download_and_decompress(${OPENSSL_URL} ${CMAKE_CURRENT_BINARY_DIR}/${OPENSSL_FILENAME}${COMPRESSED_SUFFIX} ${OPENSSL_INSTALL_DIR}) +SET(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include" CACHE PATH "openssl include directory." FORCE) +include_directories(${OPENSSL_INCLUDE_DIR}) +IF(CMAKE_SYSTEM_NAME MATCHES "Windows") + set(OPENSSL_LIBRARIES + "${OPENSSL_ROOT_DIR}/lib/libssl_static.lib" + "${OPENSSL_ROOT_DIR}/lib/libcrypto_static.lib" + ${GFLAGS_LIBRARIES} + shlwapi + CACHE FILEPATH "OPENSSL_LIBRARIES" FORCE) +ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux") + set(OPENSSL_LIBRARIES + "${OPENSSL_ROOT_DIR}/lib/libssl.a" + "${OPENSSL_ROOT_DIR}/lib/libcrypto.a" + ${GFLAGS_LIBRARIES} + -ldl -lpthread + CACHE FILEPATH "OPENSSL_LIBRARIES" FORCE) +ENDIF() \ No newline at end of file diff --git a/cmake/summary.cmake b/cmake/summary.cmake index 85c829e04..38fb35530 100755 --- a/cmake/summary.cmake +++ b/cmake/summary.cmake @@ -60,6 +60,7 @@ function(fastdeploy_summary) endif() message(STATUS " ENABLE_VISION : ${ENABLE_VISION}") message(STATUS " ENABLE_TEXT : ${ENABLE_TEXT}") + message(STATUS " ENABLE_ENCRYPTION : ${ENABLE_ENCRYPTION}") message(STATUS " ENABLE_DEBUG : ${ENABLE_DEBUG}") message(STATUS " ENABLE_VISION_VISUALIZE : ${ENABLE_VISION_VISUALIZE}") if(ANDROID) diff --git a/fastdeploy/encryption.h b/fastdeploy/encryption.h new file mode 100755 index 000000000..744bc3172 --- /dev/null +++ b/fastdeploy/encryption.h @@ -0,0 +1,20 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include "fastdeploy/core/config.h" +#ifdef ENABLE_ENCRYPTION +#include "fastdeploy/encryption/include/decrypt.h" +#include "fastdeploy/encryption/include/encrypt.h" +#endif diff --git a/fastdeploy/encryption/encryption_pybind.cc b/fastdeploy/encryption/encryption_pybind.cc new file mode 100755 index 000000000..299350204 --- /dev/null +++ b/fastdeploy/encryption/encryption_pybind.cc @@ -0,0 +1,30 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/pybind/main.h" + +namespace fastdeploy { + +void BindEncryption(pybind11::module& m) { + m.def("encrypt", [](const std::string& input, const std::string& key) { + return Encrypt(input, key); + }); + m.def("decrypt", [](const std::string& cipher, const std::string& key) { + return Decrypt(cipher, key); + }); + m.def("generate_key", []() { + return GenerateRandomKey(); + }); +} +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/include/decrypt.h b/fastdeploy/encryption/include/decrypt.h new file mode 100755 index 000000000..35d88c6f5 --- /dev/null +++ b/fastdeploy/encryption/include/decrypt.h @@ -0,0 +1,60 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +#include "fastdeploy/utils/utils.h" + +#ifndef PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H +#define PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H +namespace fastdeploy { +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief check stream is encrypted or not + * + * \param[in] cipher_stream The encrypted stream + * \return 0 if stream is encrypted. + */ +FASTDEPLOY_DECL int CheckStreamEncrypted(std::istream& cipher_stream); + + +/** \brief decrypt an encrypted stream + * + * \param[in] cipher_stream The encrypted stream + * \param[in] plain_stream The decrypted stream + * \param[in] key_base64 The key for decryption + * \return 0 if decrypt success. + */ +FASTDEPLOY_DECL int DecryptStream(std::istream& cipher_stream, + std::ostream& plain_stream, + const std::string& key_base64); + + +/** \brief decrypt an encrypted string + * + * \param[in] cipher The encrypted string + * \param[in] key The key for decryption + * \return The decrypted string + */ +FASTDEPLOY_DECL std::string Decrypt(const std::string& cipher, + const std::string& key); +#ifdef __cplusplus +} +#endif +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H diff --git a/fastdeploy/encryption/include/encrypt.h b/fastdeploy/encryption/include/encrypt.h new file mode 100755 index 000000000..0357a429c --- /dev/null +++ b/fastdeploy/encryption/include/encrypt.h @@ -0,0 +1,58 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +#include "fastdeploy/utils/utils.h" + +#ifndef PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_ENCRYPT_H +#define PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_ENCRYPT_H +namespace fastdeploy { +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief generate a random key(base64-32bytes) for an encrypted model + * + * \return std::string key + */ +FASTDEPLOY_DECL std::string GenerateRandomKey(); + +/** \brief encrypt a std::istream with key + * + * \param[in] keydata The key(base64-32bytes) for encryption + * \param[in] in_stream The plain stream + * \param[in] out_stream The ecrypted stream + * \return true if encrypt successed, otherwise false + */ +FASTDEPLOY_DECL int EncryptStream(const std::string &keydata, + std::istream& in_stream, + std::ostream& out_stream); + +/** \brief encrypt a string with key + * + * \param[in] input The input string for encryption + * \param[in] key If not given by user, generate key automatically. + * \return std::vector [encrypted string, key] + */ +FASTDEPLOY_DECL std::vector Encrypt(const std::string& input, + const std::string& key = GenerateRandomKey()); + +#ifdef __cplusplus +} +#endif +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_ENCRYPT_H diff --git a/fastdeploy/encryption/include/model_code.h b/fastdeploy/encryption/include/model_code.h new file mode 100755 index 000000000..4ff904e8c --- /dev/null +++ b/fastdeploy/encryption/include/model_code.h @@ -0,0 +1,43 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifndef DYGRAPH_DEPLOY_CPP_ENCRYPTION_INCLUDE_MODEL_CODE_H_ +#define DYGRAPH_DEPLOY_CPP_ENCRYPTION_INCLUDE_MODEL_CODE_H_ +namespace fastdeploy { +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CODE_OK = 0, + CODE_OPEN_FAILED = 100, + CODE_READ_FILE_PTR_IS_NULL = 101, + CODE_AES_GCM_ENCRYPT_FIALED = 102, + CODE_AES_GCM_DECRYPT_FIALED = 103, + CODE_KEY_NOT_MATCH = 104, + CODE_KEY_LENGTH_ABNORMAL = 105, + CODE_NOT_EXIST_DIR = 106, + CODE_FILES_EMPTY_WITH_DIR = 107, + CODE_MODEL_FILE_NOT_EXIST = 108, + CODE_PARAMS_FILE_NOT_EXIST = 109, + CODE_MODEL_YML_FILE_NOT_EXIST = 110, + CODE_MKDIR_FAILED = 111 +}; + +#ifdef __cplusplus +} +#endif +} // namespace fastdeploy +#endif // DYGRAPH_DEPLOY_CPP_ENCRYPTION_INCLUDE_MODEL_CODE_H_ diff --git a/fastdeploy/encryption/src/decrypt.cc b/fastdeploy/encryption/src/decrypt.cc new file mode 100755 index 000000000..9fa917c64 --- /dev/null +++ b/fastdeploy/encryption/src/decrypt.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include +#include +#include +#include + +#include "fastdeploy/encryption/include/decrypt.h" +#include "fastdeploy/encryption/include/model_code.h" +#include "fastdeploy/encryption/util/include/crypto/aes_gcm.h" +#include "fastdeploy/encryption/util/include/crypto/base64.h" +#include "fastdeploy/encryption/util/include/io_utils.h" +#include "fastdeploy/encryption/util/include/log.h" +#include "fastdeploy/encryption/util/include/constant/constant_model.h" +#include "fastdeploy/encryption/util/include/system_utils.h" + +namespace fastdeploy { +/** + * 0 - encrypted + * 1 - unencrypt + */ +int CheckStreamEncrypted(std::istream& cipher_stream) { + return util::SystemUtils::check_file_encrypted(cipher_stream); +} + +int DecryptStream(std::istream& cipher_stream, + std::ostream& plain_stream, + const std::string& key_base64) { + int ret = CheckStreamEncrypted(cipher_stream); + if (ret != CODE_OK) { + LOGD("[M]check file encrypted failed, code: %d", ret); + return ret; + } + + std::string key_str = + baidu::base::base64::base64_decode(key_base64.c_str()); + int ret_check = util::SystemUtils::check_key_match(key_str, cipher_stream); + if (ret_check != CODE_OK) { + LOGD("[M]check key failed in decrypt_file, code: %d", ret_check); + return CODE_KEY_NOT_MATCH; + } + + std::string aes_key = key_str.substr(0, AES_GCM_KEY_LENGTH); + std::string aes_iv = key_str.substr(16, AES_GCM_IV_LENGTH); + + cipher_stream.seekg(0, std::ios::beg); + cipher_stream.seekg(0, std::ios::end); + int data_len = cipher_stream.tellg(); + cipher_stream.seekg(0, std::ios::beg); + size_t pos = constant::MAGIC_NUMBER_LEN + + constant::VERSION_LEN + constant::TAG_LEN; + + size_t cipher_len = data_len - pos; + std::unique_ptr model_cipher( + new unsigned char[cipher_len]); + cipher_stream.seekg(pos); // skip header + cipher_stream.read(reinterpret_cast(model_cipher.get()), + cipher_len); + + size_t plain_len = data_len - AES_GCM_TAG_LENGTH - pos; + std::unique_ptr model_plain(new unsigned char[plain_len]); + + int ret_decrypt_file = util::crypto::AesGcm::decrypt_aes_gcm( + model_cipher.get(), + cipher_len, + reinterpret_cast(aes_key.c_str()), + reinterpret_cast(aes_iv.c_str()), + model_plain.get(), + reinterpret_cast(plain_len)); + + if (ret_decrypt_file != CODE_OK) { + LOGD("[M]decrypt file failed, decrypt ret = %d", ret_decrypt_file); + return ret_decrypt_file; + } + + plain_stream.write(reinterpret_cast(model_plain.get()), + plain_len); + + return CODE_OK; +} + +std::string Decrypt(const std::string& cipher, + const std::string& key) { + std::string input = baidu::base::base64::base64_decode(cipher); + std::istringstream isst_cipher(input); + std::ostringstream osst_plain; + int ret = DecryptStream(isst_cipher, osst_plain, key); + if (ret != 0) { + FDERROR << ret << ", Failed decrypt " << std::endl; + return ""; + } + return osst_plain.str(); +} + +} //namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/src/encrypt.cc b/fastdeploy/encryption/src/encrypt.cc new file mode 100755 index 000000000..942e88a59 --- /dev/null +++ b/fastdeploy/encryption/src/encrypt.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include +#include + +#include "fastdeploy/encryption/include/model_code.h" +#include "fastdeploy/encryption/include/encrypt.h" +#include "fastdeploy/encryption/util/include/constant/constant_model.h" +#include "fastdeploy/encryption/util/include/crypto/aes_gcm.h" +#include "fastdeploy/encryption/util/include/crypto/sha256_utils.h" +#include "fastdeploy/encryption/util/include/crypto/base64.h" +#include "fastdeploy/encryption/util/include/system_utils.h" +#include "fastdeploy/encryption/util/include/io_utils.h" +#include "fastdeploy/encryption/util/include/log.h" + +namespace fastdeploy { + +std::string GenerateRandomKey() { + std::string tmp = util::SystemUtils::random_key_iv(AES_GCM_KEY_LENGTH); + // return util::crypto::Base64Utils::encode(tmp); + return baidu::base::base64::base64_encode(tmp); +} + +int EncryptStream(std::istream& in_stream, std::ostream& out_stream, + const std::string &keydata) { + std::string key_str = baidu::base::base64::base64_decode(keydata); + if (key_str.length() != 32) { + return CODE_KEY_LENGTH_ABNORMAL; + } + + in_stream.seekg(0, std::ios::beg); + in_stream.seekg(0, std::ios::end); + size_t plain_len = in_stream.tellg(); + in_stream.seekg(0, std::ios::beg); + + std::unique_ptr plain(new unsigned char[plain_len]); + in_stream.read(reinterpret_cast(plain.get()), plain_len); + + std::string aes_key = key_str.substr(0, AES_GCM_KEY_LENGTH); + std::string aes_iv = key_str.substr(16, AES_GCM_IV_LENGTH); + + std::unique_ptr cipher( + new unsigned char[plain_len + AES_GCM_TAG_LENGTH]); + size_t cipher_len = 0; + int ret_encrypt = util::crypto::AesGcm::encrypt_aes_gcm( + plain.get(), + plain_len, + reinterpret_cast(aes_key.c_str()), + reinterpret_cast(aes_iv.c_str()), + cipher.get(), + reinterpret_cast(cipher_len)); + if (ret_encrypt != CODE_OK) { + LOGD("[M]aes encrypt ret code: %d", ret_encrypt); + return CODE_AES_GCM_ENCRYPT_FIALED; + } + + std::string randstr = util::SystemUtils::random_str(constant::TAG_LEN); + std::string aes_key_iv(key_str); + std::string sha256_key_iv = + util::crypto::SHA256Utils::sha256_string(aes_key_iv); + for (int i = 0; i < 64; ++i) { + randstr[i] = sha256_key_iv[i]; + } + + size_t header_len = constant::MAGIC_NUMBER_LEN + + constant::VERSION_LEN + constant::TAG_LEN; + out_stream.write(constant::MAGIC_NUMBER.c_str(), + constant::MAGIC_NUMBER_LEN); + out_stream.write(constant::VERSION.c_str(), constant::VERSION_LEN); + out_stream.write(randstr.c_str(), constant::TAG_LEN); + out_stream.write(reinterpret_cast(cipher.get()), cipher_len); + + return CODE_OK; +} + +std::vector Encrypt(const std::string& input, + const std::string& key) { + + std::istringstream isst(input); + std::ostringstream osst; + int ret = EncryptStream(isst, osst, key); + if (ret != 0) { + FDERROR << ret << ", Failed encrypt " << std::endl; + return {"", ""}; + } + + return {baidu::base::base64::base64_encode(osst.str()), key}; +} + +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/util/include/constant/constant_model.h b/fastdeploy/encryption/util/include/constant/constant_model.h new file mode 100755 index 000000000..aaebf52ba --- /dev/null +++ b/fastdeploy/encryption/util/include/constant/constant_model.h @@ -0,0 +1,30 @@ +// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once +#include +#ifndef PADDLE_MODEL_PROTECT_CONSTANT_CONSTANT_MODEL_H +#define PADDLE_MODEL_PROTECT_CONSTANT_CONSTANT_MODEL_H +namespace fastdeploy { +namespace constant { + +const static std::string MAGIC_NUMBER = "PADDLE"; // NOLINT +const static std::string VERSION = "1"; // NOLINT + +const static int MAGIC_NUMBER_LEN = 6; // NOLINT +const static int VERSION_LEN = 1; // NOLINT +const static int TAG_LEN = 128; // NOLINT + +} // namespace constant +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_CONSTANT_CONSTANT_MODEL_H diff --git a/fastdeploy/encryption/util/include/crypto/aes_gcm.h b/fastdeploy/encryption/util/include/crypto/aes_gcm.h new file mode 100755 index 000000000..2c86f98b3 --- /dev/null +++ b/fastdeploy/encryption/util/include/crypto/aes_gcm.h @@ -0,0 +1,130 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifndef PADDLE_MODEL_PROTECT_UTIL_CRYPTO_AES_GCM_H +#define PADDLE_MODEL_PROTECT_UTIL_CRYPTO_AES_GCM_H + +#include +#include +#include +#include + +#include "fastdeploy/encryption/util/include/crypto/basic.h" + +namespace fastdeploy { +namespace util { +namespace crypto { +// aes key 32 byte for 256 bit +#define AES_GCM_KEY_LENGTH 32 + +// aes tag 16 byte for 128 bit +#define AES_GCM_TAG_LENGTH 16 + +// aes iv 12 byte for 96 bit +#define AES_GCM_IV_LENGTH 16 + +class AesGcm { + public: + /** + * \brief initial aes-gcm-256 context use key & iv + * + * \note initial aes-gcm-256 context use key & iv. gcm mode + * will generate a tag(16 byte), so the ciphertext's length + * should be longer 16 byte than plaintext. + * + * + * \param plaintext plain text to be encrypted(in) + * \param len plain text's length(in) + * \param key aes key (in) + * \param iv aes iv (in) + * \param ciphertext encrypted text(out) + * \param out_len encrypted length(out) + * + * \return return 0 if successful + * -1 EVP_CIPHER_CTX_new or aes_gcm_key error + * -2 EVP_EncryptUpdate error + * -3 EVP_EncryptFinal_ex error + * -4 EVP_CIPHER_CTX_ctrl error + */ + static int encrypt_aes_gcm(const unsigned char* plaintext, const int& len, + const unsigned char* key, const unsigned char* iv, + unsigned char* ciphertext, + int& out_len); // NOLINT + /** + * \brief encrypt using aes-gcm-256 + * + * \note encrypt using aes-gcm-256 + * + * \param ciphertext cipher text to be decrypted(in) + * \param len plain text's length(in) + * \param key aes key (in) + * \param iv aes iv (in) + * \param plaintext decrypted text(out) + * \param out_len decrypted length(out) + * + * \return return 0 if successful + * -1 EVP_CIPHER_CTX_new or aes_gcm_key error + * -2 EVP_DecryptUpdate error + * -3 EVP_CIPHER_CTX_ctrl error + * -4 EVP_DecryptFinal_ex error + */ + static int decrypt_aes_gcm(const unsigned char* ciphertext, const int& len, + const unsigned char* key, const unsigned char* iv, + unsigned char* plaintext, int& out_len); // NOLINT + + private: + /** + * \brief initial aes-gcm-256 context use key & iv + * + * \note initial aes-gcm-256 context use key & iv + * + * \param key aes key (in) + * \param iv aes iv (in) + * \param e_ctx encryption context(out) + * \param d_ctx decryption context(out) + * + * \return return 0 if successful + * -1 EVP_xxcryptInit_ex error + * -2 EVP_CIPHER_CTX_ctrl error + * -3 EVP_xxcryptInit_ex error + */ + static int aes_gcm_key(const unsigned char* key, const unsigned char* iv, + EVP_CIPHER_CTX* e_ctx, EVP_CIPHER_CTX* d_ctx); + + /** + * \brief initial aes-gcm-256 context use key & iv + * + * \note initial aes-gcm-256 context use key & iv + * + * \param key aes key (in) + * \param iv aes iv (in) + * \param e_ctx encryption context(out) + * \param d_ctx decryption context(out) + * + * \return return 0 if successful + * -1 EVP_xxcryptInit_ex error + * -2 EVP_CIPHER_CTX_ctrl error + * -3 EVP_xxcryptInit_ex error + * -4 invalid key length or iv length + * -5 hex_to_byte error + */ + static int aes_gcm_key(const std::string& key_hex, const std::string& iv_hex, + EVP_CIPHER_CTX* e_ctx, EVP_CIPHER_CTX* d_ctx); +}; + +} // namespace crypto +} // namespace util +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_UTIL_CRYPTO_AES_GCM_H diff --git a/fastdeploy/encryption/util/include/crypto/base64.h b/fastdeploy/encryption/util/include/crypto/base64.h new file mode 100755 index 000000000..a1100d63e --- /dev/null +++ b/fastdeploy/encryption/util/include/crypto/base64.h @@ -0,0 +1,33 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +#ifndef PADDLE_MODEL_PROTECT_UTIL_CRYPTO_BASE64_UTILS_H +#define PADDLE_MODEL_PROTECT_UTIL_CRYPTO_BASE64_UTILS_H +namespace fastdeploy { +namespace baidu { +namespace base { +namespace base64 { + +std::string base64_encode(const std::string& input); +std::string base64_decode(const std::string& input); + +} // namespace base64 +} // namespace base +} // namespace baidu +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_BASE64_UTILS_H diff --git a/fastdeploy/encryption/util/include/crypto/basic.h b/fastdeploy/encryption/util/include/crypto/basic.h new file mode 100755 index 000000000..ed683aa6e --- /dev/null +++ b/fastdeploy/encryption/util/include/crypto/basic.h @@ -0,0 +1,78 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifndef PADDLE_MODEL_PROTECT_UTIL_BASIC_H +#define PADDLE_MODEL_PROTECT_UTIL_BASIC_H + +#include +#include +#include +#include +#include +namespace fastdeploy { +namespace util { +namespace crypto { + +class Basic { + public: + /** + * \brief byte to hex + * + * \note byte to hex. + * + * + * \param in_byte byte array(in) + * \param len byte array length(in) + * \param out_hex the hex string(in) + * + * + * \return return 0 if successful + */ + static int byte_to_hex(const unsigned char* in_byte, int len, + std::string& out_hex); // NOLINT + + /** + * \brief hex to byte + * + * \note hex to byte. + * + * + * \param in_hex the hex string(in) + * \param out_byte byte array(out) + * + * \return return 0 if successful + * -1 invalid in_hex + */ + static int hex_to_byte(const std::string& in_hex, unsigned char* out_byte); + + /** + * \brief get random char for length + * + * \note get random char for length + * + * + * \param array to be random(out) + * \param len array length(in) + * + * \return return 0 if successful + * -1 invalid parameters + */ + static int random(unsigned char* random, int len); +}; + +} // namespace crypto +} // namespace util +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_UTIL_BASIC_H diff --git a/fastdeploy/encryption/util/include/crypto/sha256_utils.h b/fastdeploy/encryption/util/include/crypto/sha256_utils.h new file mode 100755 index 000000000..61718ab27 --- /dev/null +++ b/fastdeploy/encryption/util/include/crypto/sha256_utils.h @@ -0,0 +1,40 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +#ifndef PADDLE_MODEL_PROTECT_UTIL_CRYPTO_SHA256_UTILS_H +#define PADDLE_MODEL_PROTECT_UTIL_CRYPTO_SHA256_UTILS_H +namespace fastdeploy { +namespace util { +namespace crypto { + +class SHA256Utils { + public: + static void sha256(const void* data, size_t len, unsigned char* md); + static std::vector sha256(const void* data, size_t len); + static std::vector sha256( + const std::vector& data); + static std::string sha256_string(const void* data, size_t len); + static std::string sha256_string(const std::vector& data); + static std::string sha256_string(const std::string& string); + static std::string sha256_file(const std::string& path); +}; + +} // namespace crypto +} // namespace util +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_UTIL_CRYPTO_SHA256_UTILS_H diff --git a/fastdeploy/encryption/util/include/io_utils.h b/fastdeploy/encryption/util/include/io_utils.h new file mode 100755 index 000000000..836668e5f --- /dev/null +++ b/fastdeploy/encryption/util/include/io_utils.h @@ -0,0 +1,53 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include + +#ifndef PADDLE_MODEL_PROTECT_IO_UTILS_H +#define PADDLE_MODEL_PROTECT_IO_UTILS_H +namespace fastdeploy { +namespace ioutil { + +int read_file(const char* file_path, unsigned char** dataptr, size_t* sizeptr); + +int read_with_pos_and_length(const char* file_path, unsigned char* dataptr, + size_t pos, size_t length); + +int read_with_pos(const char* file_path, size_t pos, unsigned char** dataptr, + size_t* sizeptr); + +int write_file(const char* file_path, const unsigned char* dataptr, + size_t sizeptr); + +int append_file(const char* file_path, const unsigned char* data, size_t len); + +size_t read_file_size(const char* file_path); + +int read_file_to_file(const char* src_path, const char* dst_path); + +int dir_exist_or_mkdir(const char* dir); + +/** + * @return files.size() + */ +int read_dir_files(const char* dir_path, + std::vector& files); // NOLINT + +} // namespace ioutil +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_IO_UTILS_H diff --git a/fastdeploy/encryption/util/include/log.h b/fastdeploy/encryption/util/include/log.h new file mode 100755 index 000000000..361d44dd8 --- /dev/null +++ b/fastdeploy/encryption/util/include/log.h @@ -0,0 +1,24 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifndef PADDLE_MODEL_PROTECT_UTIL_LOG_H +#define PADDLE_MODEL_PROTECT_UTIL_LOG_H + +#include +namespace fastdeploy { +#define LOGD(fmt, ...) \ + printf("{%s:%u}:" fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_UTIL_LOG_H diff --git a/fastdeploy/encryption/util/include/system_utils.h b/fastdeploy/encryption/util/include/system_utils.h new file mode 100755 index 000000000..96d0ee20b --- /dev/null +++ b/fastdeploy/encryption/util/include/system_utils.h @@ -0,0 +1,42 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include + +#ifndef PADDLE_MODEL_PROTECT_SYSTEM_UTIL_H +#define PADDLE_MODEL_PROTECT_SYSTEM_UTIL_H +namespace fastdeploy { +namespace util { + +class SystemUtils { + public: + static std::string random_key_iv(int len); + static std::string random_str(int len); + static int check_key_match(const char* key, const char* filepath); + static int check_key_match(const std::string& key, + std::istream& cipher_stream); + static int check_file_encrypted(const char* filepath); + static int check_file_encrypted(std::istream& cipher_stream); + static int check_pattern_exist(const std::vector& vecs, + const std::string& pattern); + + private: + inline static int intN(int n); +}; + +} // namespace util +} // namespace fastdeploy +#endif // PADDLE_MODEL_PROTECT_SYSTEM_UTIL_H diff --git a/fastdeploy/encryption/util/src/crypto/aes_gcm.cc b/fastdeploy/encryption/util/src/crypto/aes_gcm.cc new file mode 100755 index 000000000..37c9a3c45 --- /dev/null +++ b/fastdeploy/encryption/util/src/crypto/aes_gcm.cc @@ -0,0 +1,193 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "fastdeploy/encryption/util/include/crypto/aes_gcm.h" +namespace fastdeploy { +namespace util { +namespace crypto { + +int AesGcm::aes_gcm_key(const unsigned char* key, const unsigned char* iv, + EVP_CIPHER_CTX* e_ctx, EVP_CIPHER_CTX* d_ctx) { + int ret = 0; + if (e_ctx != NULL) { + ret = EVP_EncryptInit_ex(e_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + if (ret != 1) { + return -1; + } + ret = EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_SET_IVLEN, AES_GCM_IV_LENGTH, + NULL); + if (ret != 1) { + return -2; + } + ret = EVP_EncryptInit_ex(e_ctx, NULL, NULL, key, iv); + if (ret != 1) { + return -3; + } + } + // initial decrypt ctx + if (d_ctx != NULL) { + ret = EVP_DecryptInit_ex(d_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + if (!ret) { + return -1; + } + ret = EVP_CIPHER_CTX_ctrl(d_ctx, EVP_CTRL_GCM_SET_IVLEN, AES_GCM_IV_LENGTH, + NULL); + if (!ret) { + return -2; + } + ret = EVP_DecryptInit_ex(d_ctx, NULL, NULL, key, iv); + if (!ret) { + return -3; + } + } + return 0; +} + +int AesGcm::aes_gcm_key(const std::string& key_hex, const std::string& iv_hex, + EVP_CIPHER_CTX* e_ctx, EVP_CIPHER_CTX* d_ctx) { + // check key_hex and iv_hex length + if (key_hex.length() != AES_GCM_KEY_LENGTH * 2 || + iv_hex.length() != AES_GCM_IV_LENGTH * 2) { + return -4; + } + + unsigned char key[AES_GCM_KEY_LENGTH]; + unsigned char iv[AES_GCM_IV_LENGTH]; + + int ret = Basic::hex_to_byte(key_hex, key); + if (ret < 0) { + return -5; + } + ret = Basic::hex_to_byte(iv_hex, iv); + if (ret < 0) { + return -5; + } + return aes_gcm_key(key, iv, e_ctx, d_ctx); +} + +int AesGcm::encrypt_aes_gcm(const unsigned char* plaintext, const int& len, + const unsigned char* key, const unsigned char* iv, + unsigned char* ciphertext, int& out_len) { + EVP_CIPHER_CTX* ctx = NULL; + int ret = 0; + int update_len = 0; + int ciphertext_len = 0; + unsigned char tag_char[AES_GCM_TAG_LENGTH]; + + if (!(ctx = EVP_CIPHER_CTX_new())) { + return -1; + } + // initial context + ret = aes_gcm_key(key, iv, ctx, NULL); + if (ret) { + EVP_CIPHER_CTX_free(ctx); + return -1; + } + // encryption + ret = EVP_EncryptUpdate(ctx, ciphertext, &update_len, plaintext, len); + if (ret != 1) { + EVP_CIPHER_CTX_free(ctx); + return -2; + } + ciphertext_len = update_len; + + ret = EVP_EncryptFinal_ex(ctx, ciphertext + ciphertext_len, &update_len); + if (1 != ret) { + EVP_CIPHER_CTX_free(ctx); + return -3; + } + ciphertext_len += update_len; + + // Get the tags for authentication + ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GCM_TAG_LENGTH, + tag_char); + if (1 != ret) { + EVP_CIPHER_CTX_free(ctx); + return -4; + } + + EVP_CIPHER_CTX_free(ctx); + + // append the tags to the end of encryption text + for (int i = 0; i < AES_GCM_TAG_LENGTH; ++i) { + ciphertext[ciphertext_len + i] = tag_char[i]; + } + out_len = ciphertext_len + AES_GCM_TAG_LENGTH; + + return 0; +} + +int AesGcm::decrypt_aes_gcm(const unsigned char* ciphertext, const int& len, + const unsigned char* key, const unsigned char* iv, + unsigned char* plaintext, int& out_len) { + EVP_CIPHER_CTX* ctx = NULL; + int ret = 0; + int update_len = 0; + int cipher_len = 0; + int plaintext_len = 0; + unsigned char tag_char[AES_GCM_TAG_LENGTH]; + + // get the tag at the end of ciphertext + for (int i = 0; i < AES_GCM_TAG_LENGTH; ++i) { + tag_char[i] = ciphertext[len - AES_GCM_TAG_LENGTH + i]; + } + cipher_len = len - AES_GCM_TAG_LENGTH; + + // initial aes context + if (!(ctx = EVP_CIPHER_CTX_new())) { + return -1; + } + + ret = aes_gcm_key(key, iv, NULL, ctx); + if (ret) { + EVP_CIPHER_CTX_free(ctx); + return -1; + } + + // decryption + ret = EVP_DecryptUpdate(ctx, plaintext, &update_len, ciphertext, cipher_len); + if (ret != 1) { + EVP_CIPHER_CTX_free(ctx); + return -2; + } + plaintext_len = update_len; + + // check if the tag is equal to the decrption tag + ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GCM_TAG_LENGTH, + tag_char); + if (!ret) { + EVP_CIPHER_CTX_free(ctx); + // decrption failed + return -3; + } + + ret = EVP_DecryptFinal_ex(ctx, plaintext + update_len, &update_len); + if (ret <= 0) { + EVP_CIPHER_CTX_free(ctx); + return -4; + } + + plaintext_len += update_len; + + EVP_CIPHER_CTX_free(ctx); + + out_len = plaintext_len; + return 0; +} + +} // namespace crypto +} // namespace util +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/util/src/crypto/base64.cc b/fastdeploy/encryption/util/src/crypto/base64.cc new file mode 100755 index 000000000..a37f705c7 --- /dev/null +++ b/fastdeploy/encryption/util/src/crypto/base64.cc @@ -0,0 +1,133 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fastdeploy/encryption/util/include/crypto/base64.h" + + +namespace fastdeploy { +namespace baidu { +namespace base { +namespace base64 { +using std::string; +namespace { +const string base64_chars = // NOLINT + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +inline bool is_base64(unsigned char c) { + return isalnum(c) || (c == '+') || (c == '/'); +} + +inline size_t encode_len(size_t input_len) { return (input_len + 2) / 3 * 4; } + +void encode_char_array(unsigned char *encode_block, + const unsigned char *decode_block) { + encode_block[0] = (decode_block[0] & 0xfc) >> 2; + encode_block[1] = + ((decode_block[0] & 0x03) << 4) + ((decode_block[1] & 0xf0) >> 4); + encode_block[2] = + ((decode_block[1] & 0x0f) << 2) + ((decode_block[2] & 0xc0) >> 6); + encode_block[3] = decode_block[2] & 0x3f; +} + +void decode_char_array(unsigned char *encode_block, + unsigned char *decode_block) { + for (int i = 0; i < 4; ++i) { + encode_block[i] = base64_chars.find(encode_block[i]); + } + decode_block[0] = (encode_block[0] << 2) + ((encode_block[1] & 0x30) >> 4); + decode_block[1] = + ((encode_block[1] & 0xf) << 4) + ((encode_block[2] & 0x3c) >> 2); + decode_block[2] = ((encode_block[2] & 0x3) << 6) + encode_block[3]; +} +} // namespace + +string base64_encode(const string &input) { + string output; + size_t i = 0; + unsigned char decode_block[3]; + unsigned char encode_block[4]; + + for (string::size_type len = 0; len != input.size(); ++len) { + decode_block[i++] = input[len]; + if (i == 3) { + encode_char_array(encode_block, decode_block); + for (i = 0; i < 4; ++i) { + output += base64_chars[encode_block[i]]; + } + i = 0; + } + } + + if (i > 0) { + for (size_t j = i; j < 3; ++j) { + decode_block[j] = '\0'; + } + + encode_char_array(encode_block, decode_block); + + for (size_t j = 0; j < i + 1; ++j) { + output += base64_chars[encode_block[j]]; + } + + while (i++ < 3) { + output += '='; + } + } + + return output; +} + +string base64_decode(const string &encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int len = 0; + unsigned char encode_block[4]; + unsigned char decode_block[3]; + string output; + + while (in_len-- && (encoded_string[len] != '=') && + is_base64(encoded_string[len])) { + encode_block[i++] = encoded_string[len]; + len++; + if (i == 4) { + decode_char_array(encode_block, decode_block); + + for (int j = 0; j < 3; ++j) { + output += decode_block[j]; + } + i = 0; + } + } + + if (i > 0) { + for (int j = i; j < 4; ++j) { + encode_block[j] = 0; + } + + decode_char_array(encode_block, decode_block); + + for (int j = 0; j < i - 1; ++j) { + output += decode_block[j]; + } + } + + return output; +} + +} // namespace base64 +} // namespace base +} // namespace baidu +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/util/src/crypto/basic.cc b/fastdeploy/encryption/util/src/crypto/basic.cc new file mode 100755 index 000000000..4c9194631 --- /dev/null +++ b/fastdeploy/encryption/util/src/crypto/basic.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "fastdeploy/encryption/util/include/crypto/basic.h" +namespace fastdeploy { +namespace util { +namespace crypto { + +int Basic::byte_to_hex(const unsigned char* in_byte, int len, + std::string& out_hex) { + std::ostringstream oss; + oss << std::hex << std::setfill('0'); + for (int i = 0; i < len; ++i) { + oss << std::setw(2) << int(in_byte[i]); + } + out_hex = oss.str(); + return 0; +} + +int Basic::hex_to_byte(const std::string& in_hex, unsigned char* out_byte) { + int i = 0; + int j = 0; + int len = in_hex.length() / 2; + const unsigned char* hex; + if (in_hex.length() % 2 != 0 || out_byte == NULL) { + return -1; + } + hex = (unsigned char*)in_hex.c_str(); + + for (; j < len; i += 2, ++j) { + unsigned char high = hex[i]; + unsigned char low = hex[i + 1]; + if (high >= '0' && high <= '9') { + high = high - '0'; + } else if (high >= 'A' && high <= 'F') { + high = high - 'A' + 10; + } else if (high >= 'a' && high <= 'f') { + high = high - 'a' + 10; + } else { + return -2; + } + + if (low >= '0' && low <= '9') { + low = low - '0'; + } else if (low >= 'A' && low <= 'F') { + low = low - 'A' + 10; + } else if (low >= 'a' && low <= 'f') { + low = low - 'a' + 10; + } else { + return -2; + } + out_byte[j] = high << 4 | low; + } + return 0; +} + +int Basic::random(unsigned char* random, int len) { + std::random_device rd; + int i = 0; + if (len <= 0 || random == NULL) { + return -1; + } + for (; i < len; ++i) { + random[i] = rd() % 256; + } + return 0; +} + +} // namespace crypto +} // namespace util +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/util/src/crypto/sha256_utils.cc b/fastdeploy/encryption/util/src/crypto/sha256_utils.cc new file mode 100755 index 000000000..35e8d904f --- /dev/null +++ b/fastdeploy/encryption/util/src/crypto/sha256_utils.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include + +#include "fastdeploy/encryption/util/include/crypto/sha256_utils.h" +namespace fastdeploy { +namespace util { +namespace crypto { + +void SHA256Utils::sha256(const void* data, size_t len, unsigned char* md) { + SHA256_CTX sha_ctx = {}; + SHA256_Init(&sha_ctx); + SHA256_Update(&sha_ctx, data, len); + SHA256_Final(md, &sha_ctx); +} +std::vector SHA256Utils::sha256(const void* data, size_t len) { + std::vector md(32); + sha256(data, len, &md[0]); + return md; +} +std::vector SHA256Utils::sha256( + const std::vector& data) { + return sha256(&data[0], data.size()); +} +std::string SHA256Utils::sha256_string(const void* data, size_t len) { + std::vector md = sha256(data, len); + std::ostringstream oss; + oss << std::hex << std::setfill('0'); + for (unsigned char c : md) { + oss << std::setw(2) << int(c); + } + return oss.str(); +} +std::string SHA256Utils::sha256_string(const std::vector& data) { + return sha256_string(&data[0], data.size()); +} +std::string SHA256Utils::sha256_string(const std::string& string) { + return sha256_string(string.c_str(), string.size()); +} +std::string SHA256Utils::sha256_file(const std::string& path) { + FILE* file = fopen(path.c_str(), "rb"); + if (!file) { + return ""; + } + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha_ctx = {}; + SHA256_Init(&sha_ctx); + const int size = 32768; + void* buffer = malloc(size); + if (!buffer) { + fclose(file); + return ""; + } + int read = 0; + while ((read = fread(buffer, 1, size, file))) { + SHA256_Update(&sha_ctx, buffer, read); + } + SHA256_Final(hash, &sha_ctx); + std::ostringstream oss; + oss << std::hex << std::setfill('0'); + for (unsigned char c : hash) { + oss << std::setw(2) << int(c); + } + fclose(file); + free(buffer); + return oss.str(); +} + +} // namespace crypto +} // namespace util +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/util/src/io_utils.cc b/fastdeploy/encryption/util/src/io_utils.cc new file mode 100755 index 000000000..e15254164 --- /dev/null +++ b/fastdeploy/encryption/util/src/io_utils.cc @@ -0,0 +1,225 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef LINUX +#include +#include +#endif +#ifdef WIN32 +#include +#include +#endif + +#include +#include +#include +#include + +#include "fastdeploy/encryption/util/include/io_utils.h" +#include "fastdeploy/encryption/include/model_code.h" +#include "fastdeploy/encryption/util/include/log.h" +namespace fastdeploy { +namespace ioutil { + +int read_file(const char* file_path, unsigned char** dataptr, size_t* sizeptr) { + FILE* fp = NULL; + fp = fopen(file_path, "rb"); + if (fp == NULL) { + LOGD("[M]open file(%s) failed", file_path); + return CODE_OPEN_FAILED; + } + + fseek(fp, 0, SEEK_END); + *sizeptr = ftell(fp); + *dataptr = (unsigned char*)malloc(sizeof(unsigned char) * (*sizeptr)); + + fseek(fp, 0, SEEK_SET); + fread(*dataptr, 1, *sizeptr, fp); + fclose(fp); + + return CODE_OK; +} + +int read_with_pos_and_length(const char* file_path, unsigned char* dataptr, + size_t pos, size_t length) { + if (dataptr == NULL) { + LOGD("Read file pos dataptr = NULL"); + return CODE_READ_FILE_PTR_IS_NULL; + } + + FILE* fp = NULL; + if ((fp = fopen(file_path, "rb")) == NULL) { + LOGD("[M]open file(%s) failed", file_path); + return CODE_OPEN_FAILED; + } + + fseek(fp, pos, SEEK_SET); + fread(dataptr, 1, length, fp); + fclose(fp); + + return CODE_OK; +} + +int read_with_pos(const char* file_path, size_t pos, unsigned char** dataptr, + size_t* sizeptr) { + FILE* fp = NULL; + if ((fp = fopen(file_path, "rb")) == NULL) { + LOGD("[M]open file(%s) failed when read_with_pos", file_path); + return CODE_OPEN_FAILED; + } + + fseek(fp, 0, SEEK_END); + size_t filesize = ftell(fp); + + *sizeptr = filesize - pos; + *dataptr = (unsigned char*)malloc(sizeof(unsigned char) * (filesize - pos)); + fseek(fp, pos, SEEK_SET); + fread(*dataptr, 1, filesize - pos, fp); + fclose(fp); + + return CODE_OK; +} + +int write_file(const char* file_path, const unsigned char* dataptr, + size_t sizeptr) { + FILE* fp = NULL; + if ((fp = fopen(file_path, "wb")) == NULL) { + LOGD("[M]open file(%s) failed", file_path); + return CODE_OPEN_FAILED; + } + + fwrite(dataptr, 1, sizeptr, fp); + + fclose(fp); + return CODE_OK; +} + +int append_file(const char* file_path, const unsigned char* data, size_t len) { + FILE* fp = fopen(file_path, "ab+"); + if (fp == NULL) { + LOGD("[M]open file(%s) failed when append_file", file_path); + return CODE_OPEN_FAILED; + } + fwrite(data, sizeof(char), len, fp); + fclose(fp); + return CODE_OK; +} + +size_t read_file_size(const char* file_path) { + FILE* fp = NULL; + fp = fopen(file_path, "rb"); + if (fp == NULL) { + LOGD("[M]open file(%s) failed when read_file_size", file_path); + return 0; + } + + fseek(fp, 0, SEEK_END); + size_t filesize = ftell(fp); + fclose(fp); + + return filesize; +} + +int read_file_to_file(const char* src_path, const char* dst_path) { + FILE* infp = NULL; + if ((infp = fopen(src_path, "rb")) == NULL) { + LOGD("[M]read src file failed when read_file_to_file"); + return CODE_OPEN_FAILED; + } + + fseek(infp, 0, SEEK_END); + size_t insize = ftell(infp); + char* content = reinterpret_cast(malloc(sizeof(char) * insize)); + + fseek(infp, 0, SEEK_SET); + fread(content, 1, insize, infp); + fclose(infp); + + FILE* outfp = NULL; + if ((outfp = fopen(dst_path, "wb")) == NULL) { + LOGD("[M]open dst file failed when read_file_to_file"); + return CODE_OPEN_FAILED; + } + fwrite(content, 1, insize, outfp); + fclose(outfp); + free(content); + return CODE_OK; +} + +int read_dir_files(const char* dir_path, + std::vector& files) { // NOLINT +#ifdef LINUX + struct dirent* ptr; + DIR* dir = NULL; + dir = opendir(dir_path); + if (dir == NULL) { + return -1; // CODE_NOT_EXIST_DIR + } + while ((ptr = readdir(dir)) != NULL) { + if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { + files.push_back(ptr->d_name); + } + } + closedir(dir); +#endif +#ifdef WIN32 + intptr_t handle; + struct _finddata_t fileinfo; + + std::string tmp_dir(dir_path); + std::string::size_type idx = tmp_dir.rfind("\\*"); + if (idx == std::string::npos || idx != tmp_dir.length() - 1) { + tmp_dir.append("\\*"); + } + + handle = _findfirst(tmp_dir.c_str(), &fileinfo); + if (handle == -1) { + return -1; + } + + do { + std::cout << "File name = " << fileinfo.name << std::endl; + if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) { + files.push_back(fileinfo.name); + } + } while (!_findnext(handle, &fileinfo)); + + std::cout << files.size() << std::endl; + for (size_t i = 0; i < files.size(); i++) { + std::cout << files[i] << std::endl; + } + + _findclose(handle); +#endif + return files.size(); +} + +int dir_exist_or_mkdir(const char* dir) { +#ifdef WIN32 + if (CreateDirectory(dir, NULL)) { + // return CODE_OK; + } else { + return CODE_MKDIR_FAILED; + } +#endif +#ifdef LINUX + if (access(dir, 0) != 0) { + mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO); + } +#endif + return CODE_OK; +} + +} // namespace ioutil +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/encryption/util/src/system_utils.cc b/fastdeploy/encryption/util/src/system_utils.cc new file mode 100755 index 000000000..d04bf3144 --- /dev/null +++ b/fastdeploy/encryption/util/src/system_utils.cc @@ -0,0 +1,144 @@ +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include + +#include "fastdeploy/encryption/include/model_code.h" +#include "fastdeploy/encryption/util/include/system_utils.h" +#include "fastdeploy/encryption/util/include/crypto/basic.h" +#include "fastdeploy/encryption/util/include/crypto/sha256_utils.h" +#include "fastdeploy/encryption/util/include/io_utils.h" +#include "fastdeploy/encryption/util/include/log.h" +#include "fastdeploy/encryption/util/include/constant/constant_model.h" + +namespace fastdeploy { +namespace util { + +int SystemUtils::intN(int n) { return rand() % n; } + +std::string SystemUtils::random_key_iv(int len) { + unsigned char* tmp = (unsigned char*)malloc(sizeof(unsigned char) * len); + int ret = util::crypto::Basic::random(tmp, len); + std::string tmp_str(reinterpret_cast(tmp), len); + free(tmp); + return tmp_str; +} + +std::string SystemUtils::random_str(int len) { + unsigned char* tmp = (unsigned char*)malloc(sizeof(unsigned char) * len); + int ret = util::crypto::Basic::random(tmp, len); + std::string tmp_str(reinterpret_cast(tmp), len); + free(tmp); + return tmp_str; +} + +int SystemUtils::check_key_match(const char* key, const char* filepath) { + std::string aes_key_iv(key); + std::string sha256_aes_key_iv = + util::crypto::SHA256Utils::sha256_string(aes_key_iv); + + unsigned char* data_pos = (unsigned char*)malloc(sizeof(unsigned char) * 64); + int ret = ioutil::read_with_pos_and_length( + filepath, data_pos, constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN, + 64); + if (ret != CODE_OK) { + LOGD("[M]read file failed when check key"); + return ret; + } + + std::string check_str(reinterpret_cast(data_pos), 64); + if (strcmp(sha256_aes_key_iv.c_str(), check_str.c_str()) != 0) { + return CODE_KEY_NOT_MATCH; + } + free(data_pos); + return CODE_OK; +} + +int SystemUtils::check_key_match(const std::string& key, + std::istream& cipher_stream) { + cipher_stream.seekg(0, std::ios::beg); + std::string sha256_aes_key_iv = util::crypto::SHA256Utils::sha256_string(key); + int check_len = 64; + + std::string data_pos_str; + cipher_stream.seekg(constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN); + std::copy_n(std::istreambuf_iterator(cipher_stream), check_len, + std::back_inserter(data_pos_str)); + if (data_pos_str.size() != check_len) { + LOGD("[M]read file failed when check key"); + return CODE_OPEN_FAILED; + } + if (data_pos_str == sha256_aes_key_iv) { + return CODE_OK; + } + + return CODE_KEY_NOT_MATCH; +} + +/** + * + * @param filepath + * @return 0 - file encrypted 1 - file unencrypted + */ +int SystemUtils::check_file_encrypted(const char* filepath) { + size_t read_len = constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN; + unsigned char* data_pos = + (unsigned char*)malloc(sizeof(unsigned char) * read_len); + if (ioutil::read_with_pos_and_length(filepath, data_pos, 0, read_len) != + CODE_OK) { + LOGD("check file failed when read %s(file)", filepath); + return CODE_OPEN_FAILED; + } + + std::string tag(constant::MAGIC_NUMBER); + tag.append(constant::VERSION); + std::string check_str(reinterpret_cast(data_pos), read_len); + int ret_cmp = strcmp(tag.c_str(), check_str.c_str()) == 0 ? 0 : 1; + free(data_pos); + return ret_cmp; +} + +int SystemUtils::check_file_encrypted(std::istream& cipher_stream) { + cipher_stream.seekg(0, std::ios::beg); + size_t read_len = constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN; + std::string data_pos_str; + std::copy_n(std::istreambuf_iterator(cipher_stream), read_len, + std::back_inserter(data_pos_str)); + if (data_pos_str.size() != read_len) { + LOGD("check file failed when read cipher stream"); + return CODE_OPEN_FAILED; + } + + std::string tag(constant::MAGIC_NUMBER); + tag.append(constant::VERSION); + if (data_pos_str == tag) { + return 0; + } + + return 1; +} + +int SystemUtils::check_pattern_exist(const std::vector& vecs, + const std::string& pattern) { + if (std::find(vecs.begin(), vecs.end(), pattern) == vecs.end()) { + return -1; // not exist + } else { + return 0; // exist + } +} + +} // namespace util +} // namespace fastdeploy \ No newline at end of file diff --git a/fastdeploy/pybind/main.cc.in b/fastdeploy/pybind/main.cc.in old mode 100644 new mode 100755 index 1b227edc6..5da3ef9fc --- a/fastdeploy/pybind/main.cc.in +++ b/fastdeploy/pybind/main.cc.in @@ -20,6 +20,7 @@ void BindFDTensor(pybind11::module&); void BindRuntime(pybind11::module&); void BindFDModel(pybind11::module&); void BindVision(pybind11::module&); +void BindEncryption(pybind11::module&); void BindText(pybind11::module&); void BindPipeline(pybind11::module&); @@ -166,6 +167,13 @@ PYBIND11_MODULE(@PY_LIBRARY_NAME@, m) { m.def_submodule("pipeline", "Pipeline module of FastDeploy."); BindPipeline(pipeline_module); #endif + +#ifdef ENABLE_ENCRYPTION + auto encryption_module = + m.def_submodule("encryption", "Encryption module of FastDeploy."); + BindEncryption(encryption_module); +#endif + #ifdef ENABLE_TEXT auto text_module = m.def_submodule("text", "Text module of FastDeploy."); diff --git a/fastdeploy/pybind/main.h b/fastdeploy/pybind/main.h old mode 100644 new mode 100755 index c0ea4497a..de817bb73 --- a/fastdeploy/pybind/main.h +++ b/fastdeploy/pybind/main.h @@ -32,6 +32,10 @@ #include "fastdeploy/text.h" #endif +#ifdef ENABLE_ENCRYPTION +#include "fastdeploy/encryption.h" +#endif + #include "fastdeploy/core/float16.h" namespace fastdeploy { diff --git a/python/fastdeploy/__init__.py b/python/fastdeploy/__init__.py old mode 100644 new mode 100755 index 31735c685..730d98a73 --- a/python/fastdeploy/__init__.py +++ b/python/fastdeploy/__init__.py @@ -36,5 +36,6 @@ from . import c_lib_wrap as C from . import vision from . import pipeline from . import text +from . import encryption from .download import download, download_and_decompress, download_model, get_model_list from . import serving diff --git a/python/fastdeploy/encryption/__init__.py b/python/fastdeploy/encryption/__init__.py new file mode 100755 index 000000000..489103ff8 --- /dev/null +++ b/python/fastdeploy/encryption/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import absolute_import + +from .encryption import * diff --git a/python/fastdeploy/encryption/encryption.py b/python/fastdeploy/encryption/encryption.py new file mode 100755 index 000000000..843064258 --- /dev/null +++ b/python/fastdeploy/encryption/encryption.py @@ -0,0 +1,41 @@ +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License" +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from .. import c_lib_wrap as C + + +def generate_key(): + """generate a key for encryption + :return: key(str) + """ + return C.encryption.generate_key() + + +def encrypt(input, key=None): + """Encrypt a input string with key. + :param: input: (str) The input str for encryption + :param: key: (str,optional) The key for encryption(if not given, generate automatically.) + :return: pair(str, str) [encrypted string, key] + """ + if key is None: + key = generate_key() + return C.encryption.encrypt(input, key) + + +def decrypt(cipher, key): + """Decrypt a input cipher with key. + :param: cipher: (str) The input str for decryption + :param: key: (str) The key for decryption + :return: str(The decrypted str) + """ + return C.encryption.decrypt(cipher, key) diff --git a/python/setup.py b/python/setup.py index 108c3db94..80c6b80e9 100755 --- a/python/setup.py +++ b/python/setup.py @@ -68,6 +68,7 @@ setup_configs["ENABLE_TRT_BACKEND"] = os.getenv("ENABLE_TRT_BACKEND", "OFF") setup_configs["ENABLE_LITE_BACKEND"] = os.getenv("ENABLE_LITE_BACKEND", "OFF") setup_configs["PADDLELITE_URL"] = os.getenv("PADDLELITE_URL", "OFF") setup_configs["ENABLE_VISION"] = os.getenv("ENABLE_VISION", "OFF") +setup_configs["ENABLE_ENCRYPTION"] = os.getenv("ENABLE_ENCRYPTION", "OFF") setup_configs["ENABLE_FLYCV"] = os.getenv("ENABLE_FLYCV", "OFF") setup_configs["ENABLE_TEXT"] = os.getenv("ENABLE_TEXT", "OFF") setup_configs["WITH_GPU"] = os.getenv("WITH_GPU", "OFF") diff --git a/tests/models/test_encryption.py b/tests/models/test_encryption.py new file mode 100755 index 000000000..10670f87f --- /dev/null +++ b/tests/models/test_encryption.py @@ -0,0 +1,9 @@ +import fastdeploy as fd +import os + +if __name__ == "__main__": + input = "Hello" + cipher, key = fd.encryption.encrypt(input) + output = fd.encryption.decrypt(cipher, key) + assert input == output, "test encryption failed" + print("test encryption success")