FlyingQianMM 4 rokov pred
rodič
commit
30fa29defa
36 zmenil súbory, kde vykonal 2343 pridanie a 18 odobranie
  1. 1 1
      README.md
  2. 86 0
      dygraph/deploy/cpp/encryption/CMakeLists.txt
  3. 44 0
      dygraph/deploy/cpp/encryption/README
  4. 35 0
      dygraph/deploy/cpp/encryption/build.bat
  5. 23 0
      dygraph/deploy/cpp/encryption/build.sh
  6. 17 0
      dygraph/deploy/cpp/encryption/build_clean.bat
  7. 11 0
      dygraph/deploy/cpp/encryption/build_clean.sh
  8. 13 0
      dygraph/deploy/cpp/encryption/export_rule.map
  9. 29 0
      dygraph/deploy/cpp/encryption/include/model_code.h
  10. 50 0
      dygraph/deploy/cpp/encryption/include/paddle_model_decrypt.h
  11. 56 0
      dygraph/deploy/cpp/encryption/include/paddle_model_encrypt.h
  12. 37 0
      dygraph/deploy/cpp/encryption/include/paddle_stream_decrypt.h
  13. 99 0
      dygraph/deploy/cpp/encryption/sample/paddle_encrypt_tool.cpp
  14. 33 0
      dygraph/deploy/cpp/encryption/sample/paddle_safe_stream_test.cpp
  15. 106 0
      dygraph/deploy/cpp/encryption/src/CMakeLists.txt
  16. 15 0
      dygraph/deploy/cpp/encryption/src/constant/constant_model.h
  17. 220 0
      dygraph/deploy/cpp/encryption/src/safeapi/paddle_model_decrypt.cpp
  18. 180 0
      dygraph/deploy/cpp/encryption/src/safeapi/paddle_model_encrypt.cpp
  19. 68 0
      dygraph/deploy/cpp/encryption/src/safeapi/paddle_stream_decrypt.cpp
  20. 190 0
      dygraph/deploy/cpp/encryption/src/util/crypto/aes_gcm.cpp
  21. 128 0
      dygraph/deploy/cpp/encryption/src/util/crypto/aes_gcm.h
  22. 207 0
      dygraph/deploy/cpp/encryption/src/util/crypto/base64.cpp
  23. 30 0
      dygraph/deploy/cpp/encryption/src/util/crypto/base64.h
  24. 71 0
      dygraph/deploy/cpp/encryption/src/util/crypto/basic.cpp
  25. 68 0
      dygraph/deploy/cpp/encryption/src/util/crypto/basic.h
  26. 69 0
      dygraph/deploy/cpp/encryption/src/util/crypto/sha256_utils.cpp
  27. 23 0
      dygraph/deploy/cpp/encryption/src/util/crypto/sha256_utils.h
  28. 209 0
      dygraph/deploy/cpp/encryption/src/util/io_utils.cpp
  29. 33 0
      dygraph/deploy/cpp/encryption/src/util/io_utils.h
  30. 9 0
      dygraph/deploy/cpp/encryption/src/util/log.h
  31. 124 0
      dygraph/deploy/cpp/encryption/src/util/system_utils.cpp
  32. 26 0
      dygraph/deploy/cpp/encryption/src/util/system_utils.h
  33. 13 2
      dygraph/paddlex/cv/models/base.py
  34. 2 6
      dygraph/paddlex/cv/models/utils/det_metrics/metrics.py
  35. 16 8
      dygraph/paddlex/utils/checkpoint.py
  36. 2 1
      dygraph/requirements.txt

+ 1 - 1
README.md

@@ -54,7 +54,7 @@
 
 
 
-:heart:**您可以前往  [完整PaddleX在线使用文档目录](https://paddlex.readthedocs.io/zh_CN/develop/index.html)  查看完整*Read the Doc* 格式的文档,获得更好的阅读体验**:heart:
+:heart: **您可以前往  [完整PaddleX在线使用文档目录](https://paddlex.readthedocs.io/zh_CN/develop/index.html)  查看完整*Read the Doc* 格式的文档,获得更好的阅读体验**:heart:
 
 
 

+ 86 - 0
dygraph/deploy/cpp/encryption/CMakeLists.txt

@@ -0,0 +1,86 @@
+cmake_minimum_required(VERSION 3.12)
+project(paddle_model_protect)
+
+set(CMAKE_CXX_STANDARD 11)
+
+option(WITH_PADDLE "build with paddle libs" ON)
+
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        option(PM_EXPORTS "export symbols in windows" ON)
+        IF (PM_EXPORTS)
+                message("add_definitions of PM_EXPORTS")
+                add_definitions("-DPM_EXPORTS")
+        ENDIF ()
+ENDIF ()
+
+IF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+        # use "-fvisibility=hidden" instead of "-Wl,--version-script ${CMAKE_CURRENT_SOURCE_DIR}/export_rule.map"
+        set(CMAKE_C_VISIBILITY_PRESET hidden)
+        set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+        set(CMAKE_C_FLAGS "-g -O2 -fPIC ${CMAKE_C_FLAGS}")
+        set(CMAKE_CXX_FLAGS "-g -O2 -fPIC ${CMAKE_CXX_FLAGS}")
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows") 
+        set(CMAKE_C_FLAGS_RELEASE "/MT")
+        set(CMAKE_CXX_FLAGS_RELEASE "/MT")
+ENDIF ()
+
+SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output/bin)
+SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/output/lib)
+
+file(COPY "${PROJECT_SOURCE_DIR}/include/paddle_model_encrypt.h" DESTINATION "${PROJECT_SOURCE_DIR}/output/include/paddle_model_encrypt.h")
+IF(WITH_PADDLE)
+file(COPY "${PROJECT_SOURCE_DIR}/include/paddle_model_decrypt.h" DESTINATION "${PROJECT_SOURCE_DIR}/output/include/paddle_model_decrypt.h")
+ENDIF()
+file(COPY "${PROJECT_SOURCE_DIR}/include/paddle_stream_decrypt.h" DESTINATION "${PROJECT_SOURCE_DIR}/output/include/paddle_stream_decrypt.h")
+file(COPY "${PROJECT_SOURCE_DIR}/include/model_code.h" DESTINATION "${PROJECT_SOURCE_DIR}/output/include/model_code.h")
+
+set(SRC_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
+
+set(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rd/openssl-1.1.0k/install-${CMAKE_SYSTEM_PROCESSOR}")
+set(OPENSSL_INCLUDE "${OPENSSL_ROOT_DIR}/include")
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        set(OPENSSL_LIBS
+                "${OPENSSL_ROOT_DIR}/lib/libssl_static.lib"
+                "${OPENSSL_ROOT_DIR}/lib/libcrypto_static.lib")
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+        set(OPENSSL_LIBS
+                "${OPENSSL_ROOT_DIR}/lib/libssl.a"
+                "${OPENSSL_ROOT_DIR}/lib/libcrypto.a")
+ENDIF ()
+
+IF(WITH_PADDLE)
+set(PADDLE_INCLUDE_DIR "${PADDLE_DIR}/include")
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        # -DPADDLE_DIR=C:\developer\Paddle-developer\Paddle\build\fluid_inference_install_dir\paddle
+        # developer paddle_fluid.lib
+        # set(PADDLE_LIBS "${PADDLE_DIR}/lib/paddle_fluid.lib")
+
+        # 2.0.1 paddle_inference.lib
+        set(PADDLE_LIBS "${PADDLE_DIR}/lib/paddle_inference.lib")
+ENDIF ()
+ENDIF ()
+
+IF(WITH_PADDLE)
+message("build with paddle libs")
+include_directories(
+        include
+        ${OPENSSL_INCLUDE}
+	${PADDLE_INCLUDE_DIR}
+)
+ELSE()
+message("build no paddle libs")
+include_directories(
+        include
+        ${OPENSSL_INCLUDE}
+)
+ENDIF()
+
+
+
+IF (MSVC)
+        # Visual Studio 2015
+        set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ws2_32.lib /NODEFAULTLIB:libcmt.lib")
+        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ws2_32.lib /NODEFAULTLIB:libcmt.lib")
+ENDIF ()
+
+add_subdirectory(${SRC_ROOT_DIR})

+ 44 - 0
dygraph/deploy/cpp/encryption/README

@@ -0,0 +1,44 @@
+一、Linux
+在 centos 7 上GCC 4.8.5 编译通过
+
+Step1: 编译
+    有两种方法, 1.1需要paddle库, 并可支持加载加密模型; 1.2不需要paddle库; 默认需要PADDLE库
+
+    1.1 带有paddle库的编译, cmake 的命令在 build.sh 中, 请根据实际情况修改主要参数PADDLE_DIR的路径
+    修改脚本设置好参数后,执行build脚本
+    sh build.sh
+
+    1.2 不带paddle库的编译, cmake 的命令在 build.sh 中, 删除-DPADDLE_DIR=${PADDLE_DIR}, 并添加
+    -DWITH_PADDLE=OFF, 执行build脚本
+    sh build.sh
+
+Step2: 产出在output目录
+    2.1 头文件
+        include/model_code.h
+        include/paddle_model_encrypt.h
+        include/paddle_model_decrypt.h (注: 需要设置PADDLE库)
+        include/paddle_stream_decrypt.h
+
+    2.2 编译产出库
+        lib/libpmodel-encrypt.so
+        lib/libpmodel-decrypt.so (注: 此库编译需要设置PADDLE库)
+        lib/libpstream-decrypt.so
+
+    2.3 执行工具(使用-h参数查看)
+        bin/paddle_encrypt_tool
+
+二、Windows
+在windows 10 Visual Studio 14 2015 上编译通过
+Step1: 编译
+    修改 build.bat 中 PADDLE_DIR 的路径, 以及是否需要支持PADDLE库
+    执行 build.bat 脚本
+
+Step2:打开 blend Visual Studio 2015,
+    选择 open project -> 找到 Step1 中生成的 paddle—model-protect.sln -> 选择 Release 和 x64 -> ALL BUILD -> 右键生成
+
+三、更新说明
+日期: 2021-06-09
+1.  sdk添加支持对流进行加密, 产出为
+    libpmodel-decrypt.so 对应的头文件为paddle_model_decrypt.h, 原始的解密接口
+    libpmodel-encrypt.so 对应的头文件为paddle_model_encrypt.h, 原始的加密接口, 并添加对流加密接口
+    libpstream-decrypt.so 对应的头文件为paddle_stream_decrypt.h, 新的解密接口, 包含对流解密接口

+ 35 - 0
dygraph/deploy/cpp/encryption/build.bat

@@ -0,0 +1,35 @@
+@echo off
+set PADDLE_DIR=/path/to/Paddle/include
+
+set workPath=%~dp0
+set thirdPartyPath=%~dp03rd
+
+if exist %thirdPartyPath% (
+    echo %thirdPartyPath% exist
+    rd /S /Q %thirdPartyPath%
+)
+
+echo createDir %thirdPartyPath%
+md %thirdPartyPath%  
+
+
+cd %thirdPartyPath%
+wget --no-check-certificate https://bj.bcebos.com/paddlex/tools/openssl-1.1.0k.tar.gz
+tar -zxvf openssl-1.1.0k.tar.gz
+del openssl-1.1.0k.tar.gz
+
+cd %workPath%
+if exist %workPath%build (
+  rd /S /Q %workPath%build
+)
+if exist %workPath%\output (
+  rd /S /Q %workPath%\output
+)
+
+MD %workPath%build
+MD %workPath%\output
+cd %workPath%build
+
+cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DPADDLE_DIR=%PADDLE_DIR%
+
+cd %workPath%

+ 23 - 0
dygraph/deploy/cpp/encryption/build.sh

@@ -0,0 +1,23 @@
+PADDLE_DIR=/paddle_path/paddle_inference/paddle
+
+if [ ! -d "3rd" ]; then
+  mkdir 3rd
+fi
+
+cd 3rd
+wget https://bj.bcebos.com/paddlex/tools/openssl-1.1.0k.tar.gz
+tar -zxvf openssl-1.1.0k.tar.gz
+rm openssl-1.1.0k.tar.gz
+
+cd ..
+rm -rf build output
+mkdir build && cd build
+
+# cmake .. \
+#     -DWITH_PADDLE=OFF
+# make
+
+cmake .. \
+    -DPADDLE_DIR=${PADDLE_DIR}
+make
+

+ 17 - 0
dygraph/deploy/cpp/encryption/build_clean.bat

@@ -0,0 +1,17 @@
+@echo off
+
+set workPath=%~dp0
+set thirdPartyPath=%~dp03rd
+
+if exist %thirdPartyPath% (
+    echo %thirdPartyPath% exist
+    rd /S /Q %thirdPartyPath%
+)
+
+cd %workPath%
+if exist %workPath%build (
+  rd /S /Q %workPath%build
+)
+if exist %workPath%\output (
+  rd /S /Q %workPath%\output
+)

+ 11 - 0
dygraph/deploy/cpp/encryption/build_clean.sh

@@ -0,0 +1,11 @@
+if [ -d "3rd" ]; then
+  rm -rf 3rd
+fi
+
+if [ -d "build" ]; then
+  rm -rf build
+fi
+
+if [ -d "output" ]; then
+  rm -rf output
+fi

+ 13 - 0
dygraph/deploy/cpp/encryption/export_rule.map

@@ -0,0 +1,13 @@
+{
+    global:
+        paddle_generate_random_key;
+        paddle_encrypt_model;
+        paddle_security_load_model;
+        paddle_check_file_encrypted;
+        paddle_encrypt_dir;
+        encrypt_stream;
+        paddle_check_stream_encrypted;
+        decrypt_stream;
+    local:
+        *;
+};

+ 29 - 0
dygraph/deploy/cpp/encryption/include/model_code.h

@@ -0,0 +1,29 @@
+#ifndef PADDLE_MODEL_PROTECT_MODEL_CODE_H
+#define PADDLE_MODEL_PROTECT_MODEL_CODE_H
+
+#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
+
+#endif //PADDLE_MODEL_PROTECT_MODEL_CODE_H

+ 50 - 0
dygraph/deploy/cpp/encryption/include/paddle_model_decrypt.h

@@ -0,0 +1,50 @@
+#pragma once
+
+#include <stdio.h>
+#include "paddle_inference_api.h"
+
+#ifndef PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H
+#define PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H
+
+#ifdef WIN32
+#ifdef PM_EXPORTS
+#define PDD_MODEL_API __declspec(dllexport)
+#else
+#define PDD_MODEL_API __declspec(dllimport)
+#endif
+#endif
+#ifdef linux
+#define PDD_MODEL_API __attribute__((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * load (un)encrypted model and params to paddle::AnalysisConfig
+ * @param config
+ * @param key           加解密key(注:该SDK能符合的key信息为32字节转为BASE64编码后才能通过)
+ * @param model_file    模型文件路径
+ * @param param_file    参数文件路径
+ * @return              error_code
+ */
+PDD_MODEL_API int paddle_security_load_model(paddle::AnalysisConfig* config,
+                               const char* key,
+                               const char* model_file,
+                               const char* param_file);
+
+/**
+ * check file (un)encrypted?
+ * @param file_path
+ * @return
+ */
+PDD_MODEL_API int paddle_check_file_encrypted(const char* file_path);
+
+PDD_MODEL_API std::string decrypt_file(const char* file_path, const char* key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H

+ 56 - 0
dygraph/deploy/cpp/encryption/include/paddle_model_encrypt.h

@@ -0,0 +1,56 @@
+#pragma once
+
+#include <iostream>
+
+#ifndef PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_ENCRYPT_H
+#define PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_ENCRYPT_H
+
+#ifdef WIN32
+#ifdef PM_EXPORTS
+#define PDE_MODEL_API __declspec(dllexport)
+#else
+#define PDE_MODEL_API __declspec(dllimport)
+#endif
+#endif
+
+#ifdef linux
+#define PDE_MODEL_API __attribute__((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * generate random key
+ * 产生随机的 key 信息,如果想要使用当前 SDK,
+ * 对于传入的key信息有要求(需符合产生32字节随机值后做 BASE64 编码
+ * @return
+ */
+PDE_MODEL_API std::string paddle_generate_random_key();
+
+/**
+ * encrypt __model__, __params__ files in src_dir to dst_dir
+ * @param keydata
+ * @param src_dir
+ * @param dst_dir
+ * @return
+ */
+PDE_MODEL_API int paddle_encrypt_dir(const char* keydata, const char* src_dir, const char* dst_dir);
+
+/**
+ * encrypt file
+ * @param keydata   可使用由 paddle_generate_random_key 接口产生的key,也可以根据规则自己生成
+ * @param infile
+ * @param outfile
+ * @return          error_code
+ */
+PDE_MODEL_API int paddle_encrypt_model(const char* keydata, const char* infile, const char* outfile);
+
+PDE_MODEL_API int encrypt_stream(const std::string &keydata, std::istream &in_stream, std::ostream &out_stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_ENCRYPT_H

+ 37 - 0
dygraph/deploy/cpp/encryption/include/paddle_stream_decrypt.h

@@ -0,0 +1,37 @@
+#pragma once
+
+#include <stdio.h>
+
+#ifndef PADDLE_MODEL_PROTECT_API_PADDLE_STREAM_DECRYPT_H
+#define PADDLE_MODEL_PROTECT_API_PADDLE_STREAM_DECRYPT_H
+
+#ifdef WIN32
+#ifdef PM_EXPORTS
+#define PDD_MODEL_API __declspec(dllexport)
+#else
+#define PDD_MODEL_API __declspec(dllimport)
+#endif
+#endif
+#ifdef linux
+#define PDD_MODEL_API __attribute__((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * check file (un)encrypted?
+ * @param file_path
+ * @return
+ */
+
+PDD_MODEL_API int paddle_check_stream_encrypted(std::istream &cipher_stream);
+
+PDD_MODEL_API int decrypt_stream(std::istream &cipher_stream, std::ostream &plain_stream, const std::string &key_base64);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PADDLE_MODEL_PROTECT_API_PADDLE_MODEL_DECRYPT_H

+ 99 - 0
dygraph/deploy/cpp/encryption/sample/paddle_encrypt_tool.cpp

@@ -0,0 +1,99 @@
+#include <iostream>
+#include <cstring>
+#include "model_code.h"
+#include "paddle_model_encrypt.h"
+// #include "paddle_inference_api.h"
+
+#ifdef linux
+#define RESET           "\033[0m"
+#define BOLD            "\033[1m"
+#define BOLDGREEN       "\033[1m\033[32m"
+#elif WIN32
+#define RESET           ""
+#define BOLD            ""
+#define BOLDGREEN       ""
+#endif
+
+void help() {
+    std::cout << BOLD << "*** paddle_encrypt_tool Usage ***" << RESET << std::endl;
+
+    std::cout << "[1]Help:" << std::endl;
+    std::cout << "\t-h" << std::endl;
+    std::cout << "[2]Generate random key and encrypt dir files" << std::endl;
+    std::cout << "\t-model_dir\tmodel_dir_ori\t-save_dir\tencrypted_models" << std::endl;
+    std::cout << "[3]Generate random key for encrypt file" << std::endl;
+    std::cout << "\t-g" << std::endl;
+    std::cout << "[4]Encrypt file:" << std::endl;
+    std::cout << "\t-e\t-key\tkeydata\t-infile\tinfile\t-outfile\toutfile" << std::endl;
+}
+
+int main(int argc, char** argv) {
+
+    switch (argc) {
+        case 2:
+            if (strcmp(argv[1], "-g") == 0) {
+                std::cout << BOLD << "Generate key success: \n\t" << RESET << BOLDGREEN << paddle_generate_random_key()
+                          << RESET << std::endl;
+            } else {
+                help();
+            }
+            break;
+        case 5:
+            if (strcmp(argv[1], "-model_dir") == 0 && strcmp(argv[3], "-save_dir") == 0) {
+                std::string key_random = paddle_generate_random_key();
+                std::cout << BOLD << "Output: " << "Encryption key: \n\t" << RESET << BOLDGREEN
+                          << key_random << RESET << std::endl;
+                int ret = paddle_encrypt_dir(key_random.c_str(), argv[2], argv[4]);
+                switch (ret) {
+                    case CODE_OK:
+                        std::cout << "Success, Encrypt __model__, __params__ to " << argv[4] << "(dir) success!"
+                                  << std::endl;
+                        break;
+                    case CODE_MODEL_FILE_NOT_EXIST:
+                        std::cout << "Failed, errorcode = " << ret << ", could't find __model__(file) in " << argv[2]
+                                  << std::endl;
+                        break;
+                    case CODE_MODEL_YML_FILE_NOT_EXIST:
+                        std::cout << "Failed, errorcode = " << ret << ", could't find model.yml(file) in " << argv[2]
+                                  << std::endl;
+                        break;
+                    case CODE_PARAMS_FILE_NOT_EXIST:
+                        std::cout << "Failed, errorcode = " << ret << ", could't find __params__(file) in " << argv[2]
+                                  << std::endl;
+                        break;
+                    case CODE_NOT_EXIST_DIR:
+                        std::cout << "Failed, errorcode = " << ret << ", " << argv[2] << "(dir) not exist" << std::endl;
+                        break;
+                    case CODE_FILES_EMPTY_WITH_DIR:
+                        std::cout << "Failed, errorcode = " << ret << ", could't find any files in " << argv[2]
+                                  << std::endl;
+                        break;
+                    default:std::cout << "Failed, errorcode = " << ret << ", others" << std::endl;
+                        break;
+                }
+            } else {
+                help();
+            }
+            break;
+        case 8:
+            if (strcmp(argv[1], "-e") == 0 && strcmp(argv[2], "-key") == 0 && strcmp(argv[4], "-infile") == 0
+                && strcmp(argv[6], "-outfile") == 0) {
+                int ret_encrypt = paddle_encrypt_model(argv[3], argv[5], argv[7]);
+                if (ret_encrypt == 0) {
+                    std::cout << "Encrypt " << argv[5] << "(file) to " << argv[7] << "(file) success" << std::endl;
+                } else {
+                    std::cout << "Encrypt " << argv[5] << " failed, ret = " << ret_encrypt << std::endl;
+                }
+            } else {
+                help();
+            }
+            break;
+        default:help();
+    }
+
+#ifdef WIN32
+    system("pause");
+#endif
+
+    return 0;
+}

+ 33 - 0
dygraph/deploy/cpp/encryption/sample/paddle_safe_stream_test.cpp

@@ -0,0 +1,33 @@
+#include "../include/paddle_model_encrypt.h"
+#include "../include/paddle_stream_decrypt.h"
+
+#include <iostream>
+#include <string>
+#include <sstream>
+
+int main(){
+
+    std::string key_data = paddle_generate_random_key();
+    std::cout << "key is:" << key_data << std::endl;
+    std::istringstream isst(std::string("hello world !"));
+    std::ostringstream osst;
+    int enc_ret =  encrypt_stream(key_data, isst, osst);
+    if (enc_ret != 0){
+        std::cout << "ERROR paddle_encrypt_stream" << enc_ret <<std::endl;
+        return 0;
+    }
+    std::istringstream isst_cipher(osst.str());
+    std::ostringstream osst_plain;
+    int dec_ret = decrypt_stream(isst_cipher, osst_plain, key_data);
+    if (dec_ret != 0){
+        std::cout << "ERROR decrypt_stream " << dec_ret <<std::endl;
+        return 0;
+    }
+
+    std::cout << "data is:" << osst_plain.str() << std::endl;
+
+    return 0;
+}
+
+
+    

+ 106 - 0
dygraph/deploy/cpp/encryption/src/CMakeLists.txt

@@ -0,0 +1,106 @@
+set(SRC_COMMON
+        util/crypto/basic.cpp
+        util/system_utils.cpp
+        util/io_utils.cpp
+        util/crypto/aes_gcm.cpp
+        util/crypto/sha256_utils.cpp
+        util/crypto/base64.cpp)
+
+set(SRC_ENCRYPT
+        safeapi/paddle_model_encrypt.cpp
+        ${SRC_COMMON}
+        )
+
+set(SRC_DECRYPT
+        safeapi/paddle_model_decrypt.cpp
+        ${SRC_COMMON})
+
+# encrypt: libpmodel-encrypt.so
+add_library(pmodel-encrypt SHARED
+        ${SRC_ENCRYPT})
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        target_link_libraries(pmodel-encrypt
+                ${OPENSSL_LIBS}
+                )
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+	target_link_libraries(pmodel-encrypt
+        	${OPENSSL_LIBS}
+		-ldl -lpthread
+		)
+ENDIF ()
+
+IF(WITH_PADDLE)
+# decrypt: libpmodel-decrypt.so
+add_library(pmodel-decrypt SHARED
+        ${SRC_DECRYPT})
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        target_link_libraries(pmodel-decrypt
+                ${OPENSSL_LIBS}
+                ${PADDLE_LIBS}
+                )
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+        target_link_libraries(pmodel-decrypt
+                ${OPENSSL_LIBS}
+		-ldl -lpthread
+		)
+ENDIF ()
+ENDIF ()
+
+# decrypt: libpstream-decrypt.so
+add_library(pstream-decrypt SHARED
+        ${SRC_COMMON}
+        safeapi/paddle_stream_decrypt.cpp)
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        target_link_libraries(pstream-decrypt
+                ${OPENSSL_LIBS}
+                )
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+        target_link_libraries(pstream-decrypt
+                ${OPENSSL_LIBS}
+		-ldl -lpthread
+		)
+ENDIF ()
+
+
+# tool: paddle_encrypt_tool
+add_executable(paddle_encrypt_tool
+        ../sample/paddle_encrypt_tool.cpp
+        safeapi/paddle_model_encrypt.cpp
+        util/crypto/basic.cpp
+        util/system_utils.cpp
+        util/io_utils.cpp
+        util/crypto/aes_gcm.cpp
+        util/crypto/sha256_utils.cpp
+        util/crypto/base64.cpp)
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        target_link_libraries(paddle_encrypt_tool
+                ${OPENSSL_LIBS}
+                )
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+	target_link_libraries(paddle_encrypt_tool
+        	${OPENSSL_LIBS}
+		-ldl -lpthread
+        	)
+ENDIF ()
+
+# test: test stream encryption and decryption
+add_executable(test_enc_dec
+        ../sample/paddle_safe_stream_test.cpp
+        safeapi/paddle_stream_decrypt.cpp
+        safeapi/paddle_model_encrypt.cpp
+        util/crypto/basic.cpp
+        util/system_utils.cpp
+        util/io_utils.cpp
+        util/crypto/aes_gcm.cpp
+        util/crypto/sha256_utils.cpp
+        util/crypto/base64.cpp)
+IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
+        target_link_libraries(test_enc_dec
+                ${OPENSSL_LIBS}
+                )
+ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
+	target_link_libraries(test_enc_dec
+        	${OPENSSL_LIBS}
+		-ldl -lpthread
+        	)
+ENDIF ()

+ 15 - 0
dygraph/deploy/cpp/encryption/src/constant/constant_model.h

@@ -0,0 +1,15 @@
+#ifndef PADDLE_MODEL_PROTECT_CONSTANT_CONSTANT_MODEL_H
+#define PADDLE_MODEL_PROTECT_CONSTANT_CONSTANT_MODEL_H
+
+namespace constant {
+
+const static std::string MAGIC_NUMBER = "PADDLE";
+const static std::string VERSION = "1";
+
+const static int MAGIC_NUMBER_LEN = 6;
+const static int VERSION_LEN = 1;
+const static int TAG_LEN = 128;
+
+}
+
+#endif //PADDLE_MODEL_PROTECT_CONSTANT_CONSTANT_MODEL_H

+ 220 - 0
dygraph/deploy/cpp/encryption/src/safeapi/paddle_model_decrypt.cpp

@@ -0,0 +1,220 @@
+#include <iostream>
+#include <string>
+#include <string.h>
+#include <fstream>
+#include <memory>
+#include <iterator>
+#include <algorithm>
+#include "paddle_model_decrypt.h"
+#include "model_code.h"
+#include "../util/crypto/aes_gcm.h"
+#include "../util/io_utils.h"
+#include "../util/log.h"
+#include "../constant/constant_model.h"
+#include "../util/system_utils.h"
+#include "../util/crypto/base64.h"
+
+/**
+ * 0 - encrypted
+ * 1 - unencrypt
+ */
+int paddle_check_file_encrypted(const char* file_path) {
+    return util::SystemUtils::check_file_encrypted(file_path);
+}
+
+std::string decrypt_file(const char* file_path, const char* key) {
+    int ret = paddle_check_file_encrypted(file_path);
+    if (ret != CODE_OK) {
+        LOGD("[M]check file encrypted failed, code: %d", ret);
+        return std::string();
+    }
+
+    // std::string key_str = util::crypto::Base64Utils::decode(std::string(key));
+    std::string key_str = baidu::base::base64::base64_decode(std::string(key));
+    int ret_check = util::SystemUtils::check_key_match(key_str.c_str(), file_path);
+    if (ret_check != CODE_OK) {
+        LOGD("[M]check key failed in decrypt_file, code: %d", ret_check);
+        return std::string();
+    }
+    unsigned char* aes_key = (unsigned char*) malloc(sizeof(unsigned char) * AES_GCM_KEY_LENGTH);
+    unsigned char* aes_iv = (unsigned char*) malloc(sizeof(unsigned char) * AES_GCM_IV_LENGTH);
+    memcpy(aes_key, key_str.c_str(), AES_GCM_KEY_LENGTH);
+    memcpy(aes_iv, key_str.c_str() + 16, AES_GCM_IV_LENGTH);
+
+    size_t pos = constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN + constant::TAG_LEN;
+
+    // read encrypted data
+    unsigned char* dataptr = NULL;
+    size_t data_len = 0;
+    int ret_read_data = ioutil::read_with_pos(file_path, pos, &dataptr, &data_len);
+    if (ret_read_data != CODE_OK) {
+        LOGD("[M]read file failed, code = %d", ret_read_data);
+        return std::string();
+    }
+
+    // decrypt model data
+    size_t model_plain_len = data_len - AES_GCM_TAG_LENGTH;
+    unsigned char* model_plain = (unsigned char*) malloc(sizeof(unsigned char) * model_plain_len);
+
+    int ret_decrypt_file = 
+        util::crypto::AesGcm::decrypt_aes_gcm(
+            dataptr,
+            data_len,
+            aes_key,
+            aes_iv,
+            model_plain,
+            reinterpret_cast<int&>(model_plain_len));
+    free(dataptr);
+    free(aes_key);
+    free(aes_iv);
+    if (ret_decrypt_file != CODE_OK) {
+        free(model_plain);
+        LOGD("[M]decrypt file failed, decrypt ret = %d", ret_decrypt_file);
+        return std::string();
+    }
+    std::string result((const char*)model_plain);
+    free(model_plain);
+    return result;
+}
+
+/**
+ * support model_file encrypted or unencrypt
+ * support params_file encrypted or unencrypt
+ * all in one interface
+ */
+
+int paddle_security_load_model(
+    paddle::AnalysisConfig* config,
+    const char* key,
+    const char* model_file,
+    const char* param_file) {
+
+    // 0 - file encrypted   1 - file unencrypted
+    int m_en_flag = util::SystemUtils::check_file_encrypted(model_file);
+    if (m_en_flag == CODE_OPEN_FAILED) {
+        return m_en_flag;
+    }
+    int p_en_flag = util::SystemUtils::check_file_encrypted(param_file);
+    if (p_en_flag == CODE_OPEN_FAILED) {
+        return p_en_flag;
+    }
+
+    unsigned char* aes_key = NULL;
+    unsigned char* aes_iv = NULL;
+    if (m_en_flag == 0 || p_en_flag == 0) {
+        // std::string key_str = util::crypto::Base64Utils::decode(std::string(key));
+        std::string key_str = baidu::base::base64::base64_decode(std::string(key));
+        int ret_check = 0;
+        if (m_en_flag == 0) {
+            ret_check = util::SystemUtils::check_key_match(key_str.c_str(), model_file);
+            if (ret_check != CODE_OK) {
+                LOGD("[M]check key failed in model_file");
+                return ret_check;
+            }
+
+        }
+
+        if (p_en_flag == 0) {
+            ret_check = util::SystemUtils::check_key_match(key_str.c_str(), param_file);
+            if (ret_check != CODE_OK) {
+                LOGD("[M]check key failed in param_file");
+                return ret_check;
+            }
+        }
+        aes_key = (unsigned char*) malloc(sizeof(unsigned char) * AES_GCM_KEY_LENGTH);
+        aes_iv = (unsigned char*) malloc(sizeof(unsigned char) * AES_GCM_IV_LENGTH);
+        memcpy(aes_key, key_str.c_str(), AES_GCM_KEY_LENGTH);
+        memcpy(aes_iv, key_str.c_str() + 16, AES_GCM_IV_LENGTH);
+    }
+
+    size_t pos = constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN + constant::TAG_LEN;
+
+    // read encrypted model
+    unsigned char* model_dataptr = NULL;
+    size_t model_data_len = 0;
+    int ret_read_model = ioutil::read_with_pos(model_file, pos, &model_dataptr, &model_data_len);
+    if (ret_read_model != CODE_OK) {
+        LOGD("[M]read model failed");
+        return ret_read_model;
+    }
+
+    size_t model_plain_len = 0;
+    unsigned char* model_plain = NULL;
+    if (m_en_flag == 0) {
+        // decrypt model data
+        model_plain_len = model_data_len - AES_GCM_TAG_LENGTH;
+        model_plain = (unsigned char*) malloc(sizeof(unsigned char) * model_plain_len);
+
+        int ret_decrypt_model =
+            util::crypto::AesGcm::decrypt_aes_gcm(model_dataptr,
+                                                  model_data_len,
+                                                  aes_key,
+                                                  aes_iv,
+                                                  model_plain,
+                                                  reinterpret_cast<int&>(model_plain_len));
+        free(model_dataptr);
+        if (ret_decrypt_model != CODE_OK) {
+            free(aes_key);
+            free(aes_iv);
+            free(model_plain);
+            LOGD("[M]decrypt model failed, decrypt ret = %d", ret_decrypt_model);
+            return CODE_AES_GCM_DECRYPT_FIALED;
+        }
+    } else {
+        model_plain = model_dataptr;
+        model_plain_len = model_data_len;
+    }
+
+
+    // read encrypted params
+    unsigned char* params_dataptr = NULL;
+    size_t params_data_len = 0;
+    int ret_read_params = ioutil::read_with_pos(param_file, pos, &params_dataptr, &params_data_len);
+    if (ret_read_params != CODE_OK) {
+        LOGD("[M]read params failed");
+        return ret_read_params;
+    }
+
+    size_t params_plain_len = 0;
+    unsigned char* params_plain = NULL;
+    if (p_en_flag == 0) {
+        // decrypt params data
+        params_plain_len = params_data_len - AES_GCM_TAG_LENGTH;
+        params_plain = (unsigned char*) malloc(sizeof(unsigned char) * params_plain_len);
+
+        int ret_decrypt_params =
+            util::crypto::AesGcm::decrypt_aes_gcm(params_dataptr,
+                                                  params_data_len,
+                                                  aes_key,
+                                                  aes_iv,
+                                                  params_plain,
+                                                  reinterpret_cast<int&>(params_plain_len));
+        free(params_dataptr);
+        free(aes_key);
+        free(aes_iv);
+        if (ret_decrypt_params != CODE_OK) {
+            free(params_plain);
+            LOGD("[M]decrypt params failed, decrypt ret = %d", ret_decrypt_params);
+            return CODE_AES_GCM_DECRYPT_FIALED;
+        }
+    } else {
+        params_plain = params_dataptr;
+        params_plain_len = params_data_len;
+    }
+
+    LOGD("Prepare to set config");
+
+    config->SetModelBuffer(reinterpret_cast<const char*>(model_plain), model_plain_len,
+                           reinterpret_cast<const char*>(params_plain), params_plain_len);
+
+    if (m_en_flag == 1) {
+        free(model_dataptr);
+    }
+
+    if (p_en_flag == 1) {
+        free(params_dataptr);
+    }
+
+    return CODE_OK;
+}
+

+ 180 - 0
dygraph/deploy/cpp/encryption/src/safeapi/paddle_model_encrypt.cpp

@@ -0,0 +1,180 @@
+#include <iostream>
+#include <string>
+#include <memory>
+#include <vector>
+#include <string.h>
+#include "paddle_model_encrypt.h"
+#include "model_code.h"
+#include "../util/system_utils.h"
+#include "../util/io_utils.h"
+#include "../constant/constant_model.h"
+#include "../util/crypto/aes_gcm.h"
+#include "../util/crypto/sha256_utils.h"
+#include "../util/crypto/base64.h"
+#include "../util/log.h"
+
+std::string paddle_generate_random_key() {
+    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 paddle_encrypt_dir(const char* keydata, const char* src_dir, const char* dst_dir) {
+    std::vector<std::string> files;
+    int ret_files = ioutil::read_dir_files(src_dir, files);
+    if (ret_files == -1) {
+        return CODE_NOT_EXIST_DIR;
+    }
+    if (ret_files == 0) {
+        return CODE_FILES_EMPTY_WITH_DIR;
+    }
+
+    // check model.yml, __model__, __params__ exist or not
+    if (util::SystemUtils::check_pattern_exist(files, "model.yml")) {
+        return CODE_MODEL_YML_FILE_NOT_EXIST;
+    }
+    if (util::SystemUtils::check_pattern_exist(files, "__model__")) {
+        return CODE_MODEL_FILE_NOT_EXIST;
+    }
+    if (util::SystemUtils::check_pattern_exist(files, "__params__")) {
+        return CODE_PARAMS_FILE_NOT_EXIST;
+    }
+
+    std::string src_str(src_dir);
+    if (src_str[src_str.length() - 1] != '/') {
+        src_str.append("/");
+    }
+    std::string dst_str(dst_dir);
+    if (dst_str[dst_str.length() - 1] != '/') {
+        dst_str.append("/");
+    }
+    int ret = CODE_OK;
+    ret = ioutil::dir_exist_or_mkdir(dst_str.c_str());
+    for (int i = 0; i < files.size(); ++i) {
+        if (strcmp(files[i].c_str(), "__model__") == 0 || strcmp(files[i].c_str(), "__params__") == 0 || strcmp(files[i].c_str(), "model.yml") == 0) {
+            std::string infile = src_str + files[i];
+            std::string outfile = dst_str + files[i] + ".encrypted";
+            ret = paddle_encrypt_model(keydata, infile.c_str(), outfile.c_str());
+        } else {
+            std::string infile = src_str + files[i];
+            std::string outfile = dst_str + files[i];
+            ret = ioutil::read_file_to_file(infile.c_str(), outfile.c_str());
+        }
+
+        if (ret != CODE_OK) {
+            return ret;
+        }
+    }
+    files.clear();
+
+    return ret;
+
+}
+
+int paddle_encrypt_model(const char* keydata, const char* infile, const char* outfile) {
+
+    // std::string key_str = util::crypto::Base64Utils::decode(std::string(keydata));
+    std::string key_str = baidu::base::base64::base64_decode(std::string(keydata));
+    if (key_str.length() != 32) {
+        return CODE_KEY_LENGTH_ABNORMAL;
+    }
+
+    unsigned char* plain = NULL;
+    size_t plain_len = 0;
+    int ret_read = ioutil::read_file(infile, &plain, &plain_len);
+    if (ret_read != CODE_OK) {
+        return ret_read;
+    }
+
+    unsigned char* aes_key = (unsigned char*) malloc(sizeof(unsigned char) * AES_GCM_KEY_LENGTH);
+    unsigned char* aes_iv = (unsigned char*) malloc(sizeof(unsigned char) * AES_GCM_IV_LENGTH);
+    memcpy(aes_key, key_str.c_str(), AES_GCM_KEY_LENGTH);
+    memcpy(aes_iv, key_str.c_str() + 16, AES_GCM_IV_LENGTH);
+
+    unsigned char* cipher = (unsigned char*) malloc(sizeof(unsigned char) * (plain_len + AES_GCM_TAG_LENGTH));
+    size_t cipher_len = 0;
+    int ret_encrypt =
+        util::crypto::AesGcm::encrypt_aes_gcm(plain,
+                                              plain_len,
+                                              aes_key,
+                                              aes_iv,
+                                              cipher,
+                                              reinterpret_cast<int&>(cipher_len));
+    free(aes_key);
+    free(aes_iv);
+    if (ret_encrypt != CODE_OK) {
+        LOGD("[M]aes encrypt ret code: %d", ret_encrypt);
+        free(plain);
+        free(cipher);
+        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;
+    unsigned char* header = (unsigned char*) malloc(sizeof(unsigned char) * header_len);
+    memcpy(header, constant::MAGIC_NUMBER.c_str(), constant::MAGIC_NUMBER_LEN);
+    memcpy(header + constant::MAGIC_NUMBER_LEN, constant::VERSION.c_str(), constant::VERSION_LEN);
+    memcpy(header + constant::MAGIC_NUMBER_LEN + constant::VERSION_LEN, randstr.c_str(), constant::TAG_LEN);
+
+    int ret_write_file = ioutil::write_file(outfile, header, header_len);
+    ret_write_file = ioutil::append_file(outfile, cipher, cipher_len);
+    free(header);
+    free(cipher);
+
+    return ret_write_file;
+
+}
+
+int encrypt_stream(const std::string &keydata, std::istream &in_stream, std::ostream &out_stream) {
+
+    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<unsigned char[]> plain(new unsigned char[plain_len]);
+    in_stream.read(reinterpret_cast<char *>(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<unsigned char[]> 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<const unsigned char*>(aes_key.c_str()),
+                                              reinterpret_cast<const unsigned char*>(aes_iv.c_str()),
+                                              cipher.get(),
+                                              reinterpret_cast<int&>(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<char *>(cipher.get()), cipher_len);
+
+    return CODE_OK;
+}
+

+ 68 - 0
dygraph/deploy/cpp/encryption/src/safeapi/paddle_stream_decrypt.cpp

@@ -0,0 +1,68 @@
+#include <iostream>
+#include <string>
+#include <string.h>
+#include <fstream>
+#include <memory>
+#include <iterator>
+#include <algorithm>
+#include "paddle_stream_decrypt.h"
+#include "model_code.h"
+#include "../util/crypto/aes_gcm.h"
+#include "../util/io_utils.h"
+#include "../util/log.h"
+#include "../constant/constant_model.h"
+#include "../util/system_utils.h"
+#include "../util/crypto/base64.h"
+
+int paddle_check_stream_encrypted(std::istream &cipher_stream) {
+    return util::SystemUtils::check_file_encrypted(cipher_stream);
+}
+
+int decrypt_stream(std::istream &cipher_stream, std::ostream &plain_stream, const std::string &key_base64){
+    int ret = paddle_check_stream_encrypted(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<unsigned char[]> model_cipher(new unsigned char[cipher_len]);
+    cipher_stream.seekg(pos); // skip header
+    cipher_stream.read(reinterpret_cast<char *>(model_cipher.get()), cipher_len);
+
+    size_t plain_len = data_len - AES_GCM_TAG_LENGTH - pos;
+    std::unique_ptr<unsigned char[]> model_plain(new unsigned char[plain_len]);
+
+    int ret_decrypt_file = util::crypto::AesGcm::decrypt_aes_gcm(
+            model_cipher.get(),
+            cipher_len,
+            reinterpret_cast<const unsigned char*>(aes_key.c_str()),
+            reinterpret_cast<const unsigned char*>(aes_iv.c_str()),
+            model_plain.get(),
+            reinterpret_cast<int&>(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<const char*>(model_plain.get()), plain_len);
+
+    return CODE_OK;
+}

+ 190 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/aes_gcm.cpp

@@ -0,0 +1,190 @@
+#include <iostream>
+
+#include "aes_gcm.h"
+
+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 crypt
+} // namespace common

+ 128 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/aes_gcm.h

@@ -0,0 +1,128 @@
+#ifndef PADDLE_MODEL_PROTECT_UTIL_CRYPTO_AES_GCM_H
+#define PADDLE_MODEL_PROTECT_UTIL_CRYPTO_AES_GCM_H
+
+#include <iostream>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <string>
+
+#include "basic.h"
+
+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);
+    /**
+     * \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);
+
+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 crypt
+} // namespace common
+
+#endif // PADDLE_MODEL_PROTECT_UTIL_CRYPTO_AES_GCM_H

+ 207 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/base64.cpp

@@ -0,0 +1,207 @@
+#include "base64.h"
+
+using std::string;
+
+namespace baidu {
+namespace base {
+namespace base64 {
+
+namespace {
+const string base64_chars = 
+         "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];
+}
+}
+
+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;
+}
+
+}
+}
+}
+// #include <string>
+// #include <cassert>
+// #include <limits>
+// #include <stdexcept>
+// #include <ctype.h>
+// #include "base64_utils.h"
+
+// namespace util {
+// namespace crypto {
+
+// static const char b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+// static const char reverse_table[128] = {
+//     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+//     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+//     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+//     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+//     64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+//     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+//     64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+//     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64
+// };
+
+// std::string Base64Utils::encode(const ::std::string& data) {
+//     try {
+//         if (data.size() > (std::numeric_limits<std::string::size_type>::max() / 4u) * 3u) {
+//             throw ::std::length_error("Converting too large a string to base64.");
+//         }
+//     } catch (std::length_error& e) {
+//         printf("%s\n", e.what());
+//         return "";
+//     }
+
+//     const std::size_t binlen = data.size();
+//     std::string retval((((binlen + 2) / 3) * 4), '=');
+//     std::size_t outpos = 0;
+//     int bits_collected = 0;
+//     unsigned int accumulator = 0;
+//     const std::string::const_iterator binend = data.end();
+
+//     for (std::string::const_iterator i = data.begin(); i != binend; ++i) {
+//         accumulator = (accumulator << 8) | (*i & 0xffu);
+//         bits_collected += 8;
+//         while (bits_collected >= 6) {
+//             bits_collected -= 6;
+//             retval[outpos++] = b64_table[(accumulator >> bits_collected) & 0x3fu];
+//         }
+//     }
+//     if (bits_collected > 0) { // Any trailing bits that are missing.
+//         assert(bits_collected < 6);
+//         accumulator <<= 6 - bits_collected;
+//         retval[outpos++] = b64_table[accumulator & 0x3fu];
+//     }
+//     assert(outpos >= (retval.size() - 2));
+//     assert(outpos <= retval.size());
+//     return retval;
+// }
+
+// std::string Base64Utils::decode(const std::string& data) {
+//     std::string retval;
+//     const std::string::const_iterator last = data.end();
+//     int bits_collected = 0;
+//     unsigned int accumulator = 0;
+
+//     try {
+
+//         for (std::string::const_iterator i = data.begin(); i != last; ++i) {
+//             const int c = *i;
+//             if (isspace(c) || c == '=') {
+//                 continue;
+//             }
+//             if ((c > 127) || (c < 0) || (reverse_table[c] > 63)) {
+//                 throw ::std::invalid_argument("This contains characters not legal in a base64 encoded string.");
+//             }
+//             accumulator = (accumulator << 6) | reverse_table[c];
+//             bits_collected += 6;
+//             if (bits_collected >= 8) {
+//                 bits_collected -= 8;
+//                 retval += static_cast<char>((accumulator >> bits_collected) & 0xffu);
+//             }
+//         }
+//     } catch (std::invalid_argument& e) {
+//         printf("%s\n", e.what());
+//         return "";
+//     }
+
+//     return retval;
+// }
+
+// }
+// }
+
+

+ 30 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/base64.h

@@ -0,0 +1,30 @@
+#include <vector>
+#include <string>
+
+#ifndef PADDLE_MODEL_PROTECT_UTIL_CRYPTO_BASE64_UTILS_H
+#define PADDLE_MODEL_PROTECT_UTIL_CRYPTO_BASE64_UTILS_H
+
+namespace baidu {
+namespace base {
+namespace base64 {
+
+std::string base64_encode(const std::string& input);
+std::string base64_decode(const std::string& input);
+
+}
+}
+}
+
+// namespace util {
+// namespace crypto {
+
+// class Base64Utils {
+// public:
+//     static std::string encode(const ::std::string& data);
+
+//     static std::string decode(const ::std::string& data);
+// };
+
+// }
+// }
+#endif //PADDLE_MODEL_PROTECT_BASE64_UTILS_H

+ 71 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/basic.cpp

@@ -0,0 +1,71 @@
+#include "basic.h"
+
+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 common

+ 68 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/basic.h

@@ -0,0 +1,68 @@
+#ifndef PADDLE_MODEL_PROTECT_UTIL_BASIC_H
+#define PADDLE_MODEL_PROTECT_UTIL_BASIC_H
+
+#include <iomanip>
+#include <iostream>
+#include <random>
+#include <string>
+#include <sstream>
+
+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);
+
+    /**
+     * \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 common
+#endif // PADDLE_MODEL_PROTECT_UTIL_BASIC_H

+ 69 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/sha256_utils.cpp

@@ -0,0 +1,69 @@
+#include "sha256_utils.h"
+#include <iomanip>
+#include <stdio.h>
+#include <openssl/sha.h>
+#include <sstream>
+
+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<unsigned char> SHA256Utils::sha256(const void* data, size_t len) {
+    std::vector<unsigned char> md(32);
+    sha256(data, len, &md[0]);
+    return md;
+}
+std::vector<unsigned char> SHA256Utils::sha256(const std::vector<unsigned char>& data) {
+    return sha256(&data[0], data.size());
+}
+std::string SHA256Utils::sha256_string(const void* data, size_t len) {
+    std::vector<unsigned char> 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<unsigned char>& 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();
+}
+
+}
+}

+ 23 - 0
dygraph/deploy/cpp/encryption/src/util/crypto/sha256_utils.h

@@ -0,0 +1,23 @@
+#include <vector>
+#include <string>
+
+#ifndef PADDLE_MODEL_PROTECT_UTIL_CRYPTO_SHA256_UTILS_H
+#define PADDLE_MODEL_PROTECT_UTIL_CRYPTO_SHA256_UTILS_H
+
+namespace util {
+namespace crypto {
+
+class SHA256Utils {
+public:
+    static void sha256(const void* data, size_t len, unsigned char* md);
+    static std::vector<unsigned char> sha256(const void* data, size_t len);
+    static std::vector<unsigned char> sha256(const std::vector<unsigned char>& data);
+    static std::string sha256_string(const void* data, size_t len);
+    static std::string sha256_string(const std::vector<unsigned char>& data);
+    static std::string sha256_string(const std::string& string);
+    static std::string sha256_file(const std::string& path);
+};
+
+}
+}
+#endif //PADDLE_MODEL_PROTECT_UTIL_CRYPTO_SHA256_UTILS_H

+ 209 - 0
dygraph/deploy/cpp/encryption/src/util/io_utils.cpp

@@ -0,0 +1,209 @@
+#ifdef linux
+#include <unistd.h>
+#include <dirent.h>
+#endif
+#ifdef WIN32
+#include <windows.h>
+#include <io.h>
+#endif
+
+#include <iostream>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "io_utils.h"
+#include "model_code.h"
+#include "log.h"
+
+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 = (char*) 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<std::string>& files) {
+#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;
+}
+
+}

+ 33 - 0
dygraph/deploy/cpp/encryption/src/util/io_utils.h

@@ -0,0 +1,33 @@
+#include <iostream>
+#include <memory>
+#include <vector>
+#include <string>
+
+#ifndef PADDLE_MODEL_PROTECT_IO_UTILS_H
+#define PADDLE_MODEL_PROTECT_IO_UTILS_H
+
+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<std::string>& files);
+
+}
+#endif //PADDLE_MODEL_PROTECT_IO_UTILS_H

+ 9 - 0
dygraph/deploy/cpp/encryption/src/util/log.h

@@ -0,0 +1,9 @@
+#ifndef PADDLE_MODEL_PROTECT_UTIL_LOG_H
+#define PADDLE_MODEL_PROTECT_UTIL_LOG_H
+
+#include <stdio.h>
+
+#define LOGD(fmt,...)\
+    printf("{%s:%u}:" fmt "\n", __FUNCTION__, __LINE__,  ##__VA_ARGS__)
+
+#endif //PADDLE_MODEL_PROTECT_UTIL_LOG_H

+ 124 - 0
dygraph/deploy/cpp/encryption/src/util/system_utils.cpp

@@ -0,0 +1,124 @@
+#include <sys/timeb.h>
+#include <string.h>
+#include <model_code.h>
+#include <algorithm>
+#include <iterator>
+#include "system_utils.h"
+#include "crypto/basic.h"
+#include "crypto/sha256_utils.h"
+#include "io_utils.h"
+#include "log.h"
+#include "../constant/constant_model.h"
+
+const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(){}[]<>?~";
+
+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<const char*>(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<const char*>(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((char*) data_pos, 64);
+    free(data_pos);
+
+    if (strcmp(sha256_aes_key_iv.c_str(), check_str.c_str()) != 0) {
+        return CODE_KEY_NOT_MATCH;
+    }
+    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<char>(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);
+    int ret_cmp = strcmp(tag.c_str(), (const char*) data_pos) == 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<char>(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<std::string>& vecs, const std::string& pattern) {
+
+    if (std::find(vecs.begin(), vecs.end(), pattern) == vecs.end()) {
+        return -1; // not exist
+    } else {
+        return 0; // exist
+    }
+}
+
+}

+ 26 - 0
dygraph/deploy/cpp/encryption/src/util/system_utils.h

@@ -0,0 +1,26 @@
+#include <string>
+#include <vector>
+
+#ifndef PADDLE_MODEL_PROTECT_SYSTEM_UTIL_H
+#define PADDLE_MODEL_PROTECT_SYSTEM_UTIL_H
+
+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<std::string>& vecs, const std::string& pattern);
+
+private:
+    inline static int intN(int n);
+
+};
+
+}
+
+#endif //PADDLE_MODEL_PROTECT_SYSTEM_UTIL_H

+ 13 - 2
dygraph/paddlex/cv/models/base.py

@@ -20,6 +20,7 @@ import copy
 import math
 import yaml
 import json
+import numpy as np
 import paddle
 from paddle.io import DataLoader, DistributedBatchSampler
 from paddleslim import QAT
@@ -249,7 +250,9 @@ class BaseModel:
             collate_fn=dataset.batch_transforms,
             num_workers=dataset.num_workers,
             return_list=True,
-            use_shared_memory=use_shared_memory)
+            use_shared_memory=use_shared_memory,
+            worker_init_fn=lambda worker_id: np.random.seed(np.random.get_state()[1][0] + worker_id)
+        )
 
         return loader
 
@@ -381,7 +384,7 @@ class BaseModel:
 
             # 每间隔save_interval_epochs, 在验证集上评估和对模型进行保存
             if ema is not None:
-                weight = self.net.state_dict()
+                weight = copy.deepcopy(self.net.state_dict())
                 self.net.set_state_dict(ema.apply())
             eval_epoch_tic = time.time()
             if (i + 1) % save_interval_epochs == 0 or i == num_epochs - 1:
@@ -393,6 +396,14 @@ class BaseModel:
                     # 保存最优模型
                     if local_rank == 0:
                         self.eval_metrics, self.eval_details = eval_result
+                        if use_vdl:
+                            for k, v in self.eval_metrics.items():
+                                try:
+                                    log_writer.add_scalar(
+                                        '{}-Metrics/Eval(Epoch): {}'.format(
+                                            task_id, k), v, i + 1)
+                                except TypeError:
+                                    pass
                         logging.info('[EVAL] Finished, Epoch={}, {} .'.format(
                             i + 1, dict2str(self.eval_metrics)))
                         best_accuracy_key = list(self.eval_metrics.keys())[0]

+ 2 - 6
dygraph/paddlex/cv/models/utils/det_metrics/metrics.py

@@ -139,18 +139,14 @@ class VOCMetric(Metric):
 
     def log(self):
         map_stat = 100. * self.detection_map.get_map()
-        logging.info("mAP({:.2f}, {}) = {:.2f}%".format(
-            self.overlap_thresh, self.map_type, map_stat))
+        logging.info("bbox_map = {:.2f}%".format(map_stat))
 
     def get_results(self):
         return {'bbox': [self.detection_map.get_map()]}
 
     def get(self):
         map_stat = 100. * self.detection_map.get_map()
-        stats = {
-            "mAP({:.2f}, {})".format(self.overlap_thresh, self.map_type):
-            map_stat
-        }
+        stats = {"bbox_map": map_stat}
         return stats
 
 

+ 16 - 8
dygraph/paddlex/utils/checkpoint.py

@@ -381,21 +381,29 @@ def load_pretrain_weights(model, pretrain_weights=None, model_name=None):
             use_color=True)
 
         if os.path.exists(pretrain_weights):
-            para_state_dict = paddle.load(pretrain_weights)
+            param_state_dict = paddle.load(pretrain_weights)
             model_state_dict = model.state_dict()
-            keys = model_state_dict.keys()
+            # hack: fit for faster rcnn. Pretrain weights contain prefix of 'backbone'
+            # while res5 module is located in bbox_head.head. Replace the prefix of
+            # res5 with 'bbox_head.head' to load pretrain weights correctly.
+            for k in list(param_state_dict.keys()):
+                if 'backbone.res5' in k:
+                    new_k = k.replace('backbone', 'bbox_head.head')
+                    if new_k in model_state_dict:
+                        value = param_state_dict.pop(k)
+                        param_state_dict[new_k] = value
             num_params_loaded = 0
-            for k in keys:
-                if k not in para_state_dict:
+            for k in model_state_dict:
+                if k not in param_state_dict:
                     logging.warning("{} is not in pretrained model".format(k))
-                elif list(para_state_dict[k].shape) != list(model_state_dict[k]
-                                                            .shape):
+                elif list(param_state_dict[k].shape) != list(model_state_dict[
+                        k].shape):
                     logging.warning(
                         "[SKIP] Shape of pretrained params {} doesn't match.(Pretrained: {}, Actual: {})"
-                        .format(k, para_state_dict[k].shape, model_state_dict[
+                        .format(k, param_state_dict[k].shape, model_state_dict[
                             k].shape))
                 else:
-                    model_state_dict[k] = para_state_dict[k]
+                    model_state_dict[k] = param_state_dict[k]
                     num_params_loaded += 1
             model.set_state_dict(model_state_dict)
             logging.info("There are {}/{} variables loaded into {}.".format(

+ 2 - 1
dygraph/requirements.txt

@@ -9,5 +9,6 @@ pycocotools
 visualdl >= 2.1.1
 paddleslim == 2.1.0
 shapely
-paddlepaddle-gpu==2.1.0
+paddlepaddle-gpu==2.1.1
+numpy >= 1.20
 opencv-python