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] 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")