├── .github └── workflows │ └── whl.yml ├── .gitignore ├── LICENSE ├── README.md ├── Server ├── app.go ├── assets │ ├── 1.pdiparams │ ├── 1.pdiparams.info │ └── 1.pdmodel ├── common │ └── common.go ├── controller │ └── init.go ├── core │ └── core.go ├── go.mod ├── go.sum ├── keys │ ├── TestUser.AgentRSAPriv │ └── TestUser.AgentRSAPub └── model │ └── model.go ├── agentenc ├── __init__.py ├── encryptors │ ├── __init__.py │ ├── aes.py │ ├── base.py │ └── rsa.py └── ops │ ├── __init__.py │ ├── aes.py │ ├── base.py │ └── rsa.py ├── example └── paddlepaddle │ ├── key.PRIVATE │ ├── key.PUBLIC │ ├── make_model.py │ ├── test_model_paddleinference.py │ └── test_model_ppqi.py └── setup.py /.github/workflows/whl.yml: -------------------------------------------------------------------------------- 1 | name: Whl Action 2 | 3 | on: 4 | release: 5 | types: [published] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Set up Python 15 | uses: actions/setup-python@v2 16 | with: 17 | python-version: '3.x' 18 | - name: Install dependencies 19 | run: | 20 | python -m pip install --upgrade pip 21 | pip install build 22 | - name: Build package 23 | run: python -m build 24 | - name: Publish package 25 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 26 | with: 27 | user: __token__ 28 | password: ${{ secrets.PYPI_API_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AgentEncryption 2 | 飞桨模型加密库 - EAP阶段 3 | 在分发加密模型时,请务必进行不限于以下的操作方可避免轻易破解 4 | - [x] 加密深度学习框架以及其相关的Python库,至少为pyd格式 5 | - [x] 加密AgentEncryption库,至少为pyd格式 6 | - [x] 限制用户只能使用你提供的Python环境 7 | 8 | 9 | 10 | > 飞桨推理模型加密可参考[从内存中加载加密飞桨推理模型](./example/paddlepaddle) 11 | > 1. [加密飞桨模型](./example/paddlepaddle/make_model.py) 12 | > 2. [借助PPQI推理加密的飞桨模型](./example/paddlepaddle/test_model_ppqi.py) 13 | > 3. [借助PaddleInference推理加密的飞桨模型](./example/paddlepaddle/test_model_paddleinference.py) 14 | 15 | ## 快速使用 16 | * 如下是几个简单的示例代码: 17 | * 数据加密: 18 | 19 | ```python 20 | # 导入 RSA 加密器 21 | from agentenc import RSAEncryptor 22 | 23 | # 初始化 RSA 加密器 24 | encryptor = RSAEncryptor(bits=1024) 25 | 26 | # 构建原始数据 27 | pure_data = { 28 | 'int': 100, 29 | 'float': 0.01, 30 | 'str': 'hello', 31 | 'list': [100, 0.01, 'hello'] 32 | } 33 | 34 | # 数据加密 35 | key = encryptor.encode( 36 | input=pure_data, 37 | output='out', 38 | format='pkl', 39 | keys_saving_path='key' 40 | ) 41 | 42 | # 打印随机生成的密钥 43 | print(key) 44 | 45 | ''' 46 | { 47 | 'private_key': b'-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQDQq3mzdfDYjg8ool1Jl5WrmFAkJWarokIQAzq/3wT+cbNUy/zv\nqxHCn7bYsifvx5nLnfCL7cm3BVygnB4clP8p6EAlO8KcocC/6WfCyTW5gw23z5Tc\ntzSzAERtNTGwDst3RAnEDeJ2crNi/xSs2Wa6k1bNkxNFUehEd4ExpYFwLQIDAQAB\nAoGAWmYG9aOBANfeIkzgnBqSyQFVqqsXRQConPZBM9EigTZxqakrfQq/yXBWjp7z\npTFz452bEYukqOimPaAUfW5g8ZYxndN2G1ctWMPg3KrJ++7FYFJJhJ223IOmSmB4\nKf2FyVjBNUTzKchBdxHcLqAQX1DNXnWrJ5cWc2pS0olz+BMCQQDTZ8hqIT1UPclk\noPTX6gC+874D+GNa5r4CsMMiUZNrN7hCXEwZJ+3kR14vcJkDd2QVg8cR6VSxP9Vg\nBg5XuD2jAkEA/K/3mtKMDhX5HjNUfoBzLBSJreAVMOcGGrLCLFob+8t64456SQ8I\nOKABsocpKaRp+s3loi6obGoRwIQ5PBTX7wJBAMp60pfj8kunSidZimjqtYAvEEXZ\nN8Au1Lra9mr+WwYMPi1BHZnShqVoPauOWt/ZEEETEC31n6qNCx+HbWFTE6UCQEfF\n16ezPDLYDO2GGO7hn1Ua9ExeBMbiJ/q3Ya3lXmNz1ZEDLDrKOUSUNkc2WvvIBo5F\no38gj5hTvH0ZUYR+SyMCQEnnTVZXhtU7jtyOfEXsTqUtZIVo01sJ5SoekGrnZ0Ht\n8PxyjyOc5IFWieKGUfZQ3ZdKDm95dvAyKpkDa8tqMCM=\n-----END RSA PRIVATE KEY-----', 48 | 'public_key': b'-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQq3mzdfDYjg8ool1Jl5WrmFAk\nJWarokIQAzq/3wT+cbNUy/zvqxHCn7bYsifvx5nLnfCL7cm3BVygnB4clP8p6EAl\nO8KcocC/6WfCyTW5gw23z5TctzSzAERtNTGwDst3RAnEDeJ2crNi/xSs2Wa6k1bN\nkxNFUehEd4ExpYFwLQIDAQAB\n-----END PUBLIC KEY-----' 49 | } 50 | ''' 51 | 52 | # 使用解密函数对文件进行解密 53 | data = RSAEncryptor.decode( 54 | inp='out.pkl', 55 | private_key=key['private_key'] 56 | ) 57 | 58 | # 输入与输出数据对比 59 | print(data == pure_data) 60 | 61 | ''' 62 | True 63 | ''' 64 | ``` 65 | 66 | * 数据解密: 67 | 68 | ```python 69 | # 导入基础加密器 70 | from agentenc import Encryptor 71 | 72 | # 读取私钥 73 | private_key = open('key.PRIVATE', 'rb').read() 74 | 75 | # 使用解密函数对文件进行解密 76 | data = Encryptor.decode( 77 | inp='out.pkl', 78 | private_key=private_key 79 | ) 80 | 81 | # 输入与输出数据对比 82 | print(data) 83 | 84 | ''' 85 | { 86 | 'int': 100, 87 | 'float': 0.01, 88 | 'str': 'hello', 89 | 'list': [100, 0.01, 'hello'] 90 | } 91 | ''' 92 | ``` 93 | 94 | ## Contact us 95 | Email : [agentmaker@163.com]()
96 | QQ Group : 1005109853 97 | -------------------------------------------------------------------------------- /Server/app.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "agentencryption/controller" 5 | "log" 6 | ) 7 | 8 | func main() { 9 | router := controller.InitServer() 10 | err := router.Run(":6666") 11 | if err != nil { 12 | log.Fatalln("Failed to start server: ", err) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Server/assets/1.pdiparams: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMaker/AgentEncryption/b0c878199db2898ea9d08c6a2e0b652971662bab/Server/assets/1.pdiparams -------------------------------------------------------------------------------- /Server/assets/1.pdiparams.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMaker/AgentEncryption/b0c878199db2898ea9d08c6a2e0b652971662bab/Server/assets/1.pdiparams.info -------------------------------------------------------------------------------- /Server/assets/1.pdmodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgentMaker/AgentEncryption/b0c878199db2898ea9d08c6a2e0b652971662bab/Server/assets/1.pdmodel -------------------------------------------------------------------------------- /Server/common/common.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "bytes" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | "crypto/x509" 8 | "encoding/pem" 9 | "log" 10 | ) 11 | 12 | func PartEncrypt(PublicKey *rsa.PublicKey, File []byte) (data []byte, err error) { 13 | 14 | FileSize := len(File) 15 | 16 | OnceStep := PublicKey.Size() - 11 17 | 18 | FileOffset := 0 19 | 20 | var FileBuffer bytes.Buffer 21 | 22 | // Model Encrypt 23 | 24 | for FileOffset < FileSize { 25 | EndIndex := FileOffset + OnceStep 26 | if EndIndex > FileSize { // 当EndIndex比文件大的时候 27 | EndIndex = FileSize 28 | } 29 | // 分段加密 30 | Part, err := rsa.EncryptPKCS1v15(rand.Reader, PublicKey, File[FileOffset:EndIndex]) 31 | if err != nil { 32 | return nil, err 33 | } 34 | FileBuffer.Write(Part) 35 | FileOffset = EndIndex 36 | } 37 | return FileBuffer.Bytes(), nil 38 | } 39 | 40 | func CreateRsaKey(bits int) (prikey string, pubkey string, err error) { 41 | // 生成私钥文件 42 | privateKey, err := rsa.GenerateKey(rand.Reader, bits) 43 | if err != nil { 44 | log.Println("CreateKeyError: ", err) 45 | return "", "", err 46 | } 47 | derStream := x509.MarshalPKCS1PrivateKey(privateKey) 48 | block := &pem.Block{ 49 | Type: "RSA PRIVATE KEY", 50 | Bytes: derStream, 51 | } 52 | // 向内存输出私钥 53 | prikey = string(pem.EncodeToMemory(block)) 54 | 55 | //生成公钥文件 56 | publicKey := &privateKey.PublicKey 57 | derPkix, err := x509.MarshalPKIXPublicKey(publicKey) 58 | if err != nil { 59 | log.Println("CreateKeyError: ", err) 60 | return "", "", err 61 | } 62 | block = &pem.Block{ 63 | Type: "PUBLIC KEY", 64 | Bytes: derPkix, 65 | } 66 | // 向内存输出公钥 67 | pubkey = string(pem.EncodeToMemory(block)) 68 | return 69 | } 70 | -------------------------------------------------------------------------------- /Server/controller/init.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "agentencryption/core" 5 | 6 | "github.com/gin-contrib/cors" 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | func InitServer() *gin.Engine { 11 | route := gin.Default() 12 | route.Use(cors.Default()) 13 | route.POST("/Register", core.Register) 14 | route.POST("/GetModel", core.GetModel) 15 | return route 16 | } 17 | -------------------------------------------------------------------------------- /Server/core/core.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "agentencryption/common" 5 | "agentencryption/model" 6 | "crypto/rsa" 7 | "crypto/x509" 8 | "encoding/base64" 9 | "encoding/pem" 10 | "fmt" 11 | "io/ioutil" 12 | "log" 13 | "net/http" 14 | 15 | "github.com/gin-gonic/gin" 16 | "github.com/gin-gonic/gin/binding" 17 | uuid "github.com/satori/go.uuid" 18 | ) 19 | 20 | func JSONFail(ctx *gin.Context, retCode int, errorMsg string) { 21 | 22 | ctx.JSON(http.StatusOK, gin.H{ 23 | "Code": retCode, 24 | "Status": "Fail", 25 | "RequestID": uuid.NewV4(), 26 | "ErrorMsg": errorMsg, 27 | }) 28 | } 29 | 30 | func JSONSuccess(ctx *gin.Context, result interface{}) { 31 | 32 | ctx.JSON(http.StatusOK, gin.H{ 33 | "Code": 0, 34 | "Status": "Success", 35 | "RequestID": uuid.NewV4(), 36 | "Result": result, 37 | }) 38 | } 39 | 40 | func Register(ctx *gin.Context) { 41 | var RegParams model.RegisterParams 42 | err := ctx.ShouldBindBodyWith(&RegParams, binding.JSON) 43 | if err != nil { 44 | JSONFail(ctx, -1, err.Error()) 45 | log.Println("RequestParamsError: ", err) 46 | return 47 | } 48 | 49 | if RegParams.Username != "TestUser" || RegParams.Password != "test123" { 50 | JSONFail(ctx, -1, "Auth Error: Username or Password doesn't match.") 51 | log.Println("Auth Error: ", "UNAME OR PASSWD DOESN'T MATCH") 52 | return 53 | } 54 | 55 | prikey, pubkey, err := common.CreateRsaKey(2048) // Default: 8192 56 | 57 | if err != nil { 58 | JSONFail(ctx, -2, err.Error()) 59 | log.Println("CreateRSAError: ", err) 60 | return 61 | } 62 | 63 | var Response model.RegisterResp 64 | Response.RSAPrivate = prikey 65 | 66 | err = ioutil.WriteFile("./keys/"+fmt.Sprint(RegParams.Username)+".AgentRSAPriv", []byte(prikey), 0700) 67 | 68 | if err != nil { 69 | JSONFail(ctx, -2, err.Error()) 70 | log.Println("CreateRSAError: ", err) 71 | return 72 | } 73 | 74 | err = ioutil.WriteFile("./keys/"+fmt.Sprint(RegParams.Username)+".AgentRSAPub", []byte(pubkey), 0700) 75 | 76 | if err != nil { 77 | JSONFail(ctx, -2, err.Error()) 78 | log.Println("CreateRSAError: ", err) 79 | return 80 | } 81 | 82 | JSONSuccess(ctx, Response) 83 | } 84 | 85 | func GetModel(ctx *gin.Context) { 86 | var GetParams model.GetModelParams 87 | err := ctx.ShouldBindBodyWith(&GetParams, binding.JSON) 88 | if err != nil { 89 | JSONFail(ctx, -1, err.Error()) 90 | log.Println("RequestParamsError: ", err) 91 | return 92 | } 93 | 94 | if GetParams.AccountInfo.Username != "TestUser" || GetParams.AccountInfo.Password != "test123" { 95 | JSONFail(ctx, -1, "Auth Error: Username or Password doesn't match.") 96 | log.Println("Auth Error: ", "UNAME OR PASSWD DOESN'T MATCH") 97 | return 98 | } 99 | 100 | ModelID := fmt.Sprint(GetParams.ID) 101 | 102 | ModelParams, err := ioutil.ReadFile("./assets/" + ModelID + ".pdiparams") 103 | if err != nil { 104 | JSONFail(ctx, -3, err.Error()) 105 | log.Println(err) 106 | return 107 | } 108 | ModelParamInfo, err := ioutil.ReadFile("./assets/" + ModelID + ".pdiparams.info") 109 | if err != nil { 110 | JSONFail(ctx, -3, err.Error()) 111 | log.Println(err) 112 | return 113 | } 114 | Model, err := ioutil.ReadFile("./assets/" + ModelID + ".pdmodel") 115 | if err != nil { 116 | JSONFail(ctx, -3, err.Error()) 117 | log.Println(err) 118 | return 119 | } 120 | 121 | PublicKeyFile, err := ioutil.ReadFile("./keys/" + GetParams.AccountInfo.Username + ".AgentRSAPub") 122 | if err != nil { 123 | JSONFail(ctx, -4, err.Error()) 124 | log.Println(err) 125 | return 126 | } 127 | 128 | Block, _ := pem.Decode(PublicKeyFile) 129 | 130 | KeyInterface, err := x509.ParsePKIXPublicKey(Block.Bytes) 131 | 132 | if err != nil { 133 | JSONFail(ctx, -4, err.Error()) 134 | log.Println(err) 135 | return 136 | } 137 | 138 | PublicKey := KeyInterface.(*rsa.PublicKey) 139 | 140 | Model, err = common.PartEncrypt(PublicKey, Model) 141 | 142 | if err != nil { 143 | JSONFail(ctx, -5, err.Error()) 144 | log.Println(err) 145 | return 146 | } 147 | 148 | ModelParams, err = common.PartEncrypt(PublicKey, ModelParams) 149 | 150 | if err != nil { 151 | JSONFail(ctx, -5, err.Error()) 152 | log.Println(err) 153 | return 154 | } 155 | 156 | ModelParamInfo, err = common.PartEncrypt(PublicKey, ModelParamInfo) 157 | 158 | if err != nil { 159 | JSONFail(ctx, -5, err.Error()) 160 | log.Println(err) 161 | return 162 | } 163 | 164 | var ModelData model.ModelResp 165 | ModelData.ID = GetParams.ID 166 | ModelData.Model = base64.StdEncoding.EncodeToString(Model) 167 | ModelData.ModelParam = base64.StdEncoding.EncodeToString(ModelParams) 168 | ModelData.ModelParamInfo = base64.StdEncoding.EncodeToString(ModelParamInfo) 169 | 170 | JSONSuccess(ctx, ModelData) 171 | } 172 | -------------------------------------------------------------------------------- /Server/go.mod: -------------------------------------------------------------------------------- 1 | module agentencryption 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gin-contrib/cors v1.3.1 7 | github.com/gin-gonic/gin v1.5.0 8 | ) 9 | 10 | require ( 11 | github.com/gin-contrib/sse v0.1.0 // indirect 12 | github.com/go-playground/locales v0.12.1 // indirect 13 | github.com/go-playground/universal-translator v0.16.0 // indirect 14 | github.com/golang/protobuf v1.3.2 // indirect 15 | github.com/json-iterator/go v1.1.7 // indirect 16 | github.com/leodido/go-urn v1.1.0 // indirect 17 | github.com/mattn/go-isatty v0.0.9 // indirect 18 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 19 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect 20 | github.com/satori/go.uuid v1.2.0 // indirect 21 | github.com/ugorji/go/codec v1.1.7 // indirect 22 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // indirect 23 | gopkg.in/go-playground/validator.v9 v9.29.1 // indirect 24 | gopkg.in/yaml.v2 v2.2.2 // indirect 25 | ) 26 | -------------------------------------------------------------------------------- /Server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA= 5 | github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk= 6 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 7 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 8 | github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc= 9 | github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= 10 | github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= 11 | github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= 12 | github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= 13 | github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= 14 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 15 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 16 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 17 | github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= 18 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 19 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 20 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 21 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 22 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 23 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 24 | github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= 25 | github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= 26 | github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= 27 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 28 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 29 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 30 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 31 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 32 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 33 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 34 | github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= 35 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 36 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 37 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 38 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 39 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 40 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 41 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 42 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 43 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 44 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= 45 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 46 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 47 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 48 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 49 | gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= 50 | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= 51 | gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= 52 | gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= 53 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 54 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 55 | -------------------------------------------------------------------------------- /Server/keys/TestUser.AgentRSAPriv: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEApI5g5z/9TbJh/SVHMGSGwXCMcycgN3xoq4ni4dFvdI+t0Xmg 3 | qdszayPlKjTUQr/MrILlRFXW7U6xXGL4gMCY9YRbz/cHjfYAfk4+xVSN2PBO08bV 4 | B7pf9njBckgkGlm6SOAoePk9c5t08qkOYoGh0pqJQsVo8nIu75kO5B6oh1Lj0YCG 5 | yV0zrOT6fWawjkNG6n/zUzKmXCXx5FxRW6EH0n43kYg7gacqjCfmaClU7C/fMCq1 6 | 61lKHhaHfBV1Zpg/aHY67j6UCBvAAypSdl/ML260IQNv0tlQgLRdz+eBDNiRQIWW 7 | PWJkAV9y1iquvzKJR1VJM26Xkzc/9MxaWeGXvQIDAQABAoIBACeyeUoQM8lEmUL6 8 | dTwFZETSI++7ppf8GTwYnXUgkySpbKM2Fj4jtTnJhQUzjWk03+lWAn0DwD+rVjoV 9 | XiGhVMUV0xhOXbIvgFr4AUiVZ0rIXhvUwZuFqJTK+M/a+2qn7rqZ6OmWJu72t7W6 10 | ds/oueMWiLpk6TZjuVLvt5nsk3dhcq7Qsap+8hzwSp4M9D1yaixFbv69jte86SXd 11 | msM4QJ1LF1IOPJ7eU5/k/tNDBgMtB8CZqhSlbt9Btfdt3J/2GIIuxQIJK5nxmjZI 12 | wKzRtkw6cz3Y+e7Az5/QgWDIasRDcLDNhou3vl5a1gJN4HZRjjAVlpiavFayEKfZ 13 | 0cXry4ECgYEAyqNGUnC1/1PlVejjoV/j2mwi78NVcMTlZFQk+D61f3WQ/jCoIQ8O 14 | crEDqu4kkEMhsyJz3oI3WMB4TvwEID3WS7jbRDLWAmv2jezkUeF32zMWOFXGfnGx 15 | Hnm3hgbJmJQlsAYrlMA2DKbApMISf4ocKPrlCSF8FaZ5QNVrEeFYP60CgYEAz+PZ 16 | oDt/Q7Mmk4pRWCMXoiTLQ0q/GTNyaS7S2T7PbPDMoqRfO/KhOjNIQ8NOrnlFcACb 17 | oJxnvUe3dfrnt7VTzevJnFVtNKXwNkQ2JpNgr3C5Qdpj+Egk4tY/LfjzwCyPLTK8 18 | 2qPFW146V5jnyhl+1zArncm1SRESNPq+0NixelECgYAlZOgPQplzWsoRhn6rQwTL 19 | Q/VWhZd4zfz+/MAtx3S65rkxD02XfC3QYHYqzvOUY68OXadAQotwJ2SMPtmMEZ1A 20 | MAbWmQMBQ2cmXbbsnUz++Hh7QOj2YIis9Q03AH2nWH9z8k+MjcPrpcIbJW1Ad/4m 21 | WdZ2TuWVITlzC29Mx2b/qQKBgQCkHxKhUDdhoB61Xf5oIZQ32uppnqoNYDNT3LZy 22 | 8gZZ0CUNxcy1jBBC3VeQv7DvRyhNiv1SKAgyQ1sQFlw3CT03FY3eEQcdCGACx4kk 23 | nTc4ajqnRZ2k1nfgaRoJ1j/BGKyUFzlHNwHI5zQSEdH0GHqtsgbNFAA9xe9kygw4 24 | 3soGcQKBgFoi/f61G1ZTl+RQf+Qrzo3J3C/Q7ivA8XdLoshtXttp13IwEh3I+vxx 25 | QLMaCzC2h8lBhyEuTlGnZLIQ1S7gunglmh7i/AiRxPrYwr0zI6EmkYK5GzE3chN3 26 | DqwvN7Hk4OIXJplQGPIWtog9eZG+wsz4WN6AWx7N7tDaOL+Z+4Nq 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /Server/keys/TestUser.AgentRSAPub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApI5g5z/9TbJh/SVHMGSG 3 | wXCMcycgN3xoq4ni4dFvdI+t0XmgqdszayPlKjTUQr/MrILlRFXW7U6xXGL4gMCY 4 | 9YRbz/cHjfYAfk4+xVSN2PBO08bVB7pf9njBckgkGlm6SOAoePk9c5t08qkOYoGh 5 | 0pqJQsVo8nIu75kO5B6oh1Lj0YCGyV0zrOT6fWawjkNG6n/zUzKmXCXx5FxRW6EH 6 | 0n43kYg7gacqjCfmaClU7C/fMCq161lKHhaHfBV1Zpg/aHY67j6UCBvAAypSdl/M 7 | L260IQNv0tlQgLRdz+eBDNiRQIWWPWJkAV9y1iquvzKJR1VJM26Xkzc/9MxaWeGX 8 | vQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /Server/model/model.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type RegisterParams struct { 4 | Username string `json:"Username"` 5 | Password string `json:"Password"` 6 | } 7 | 8 | type RegisterResp struct { 9 | RSAPrivate string `json:"PrivateKey"` 10 | } 11 | 12 | type GetModelParams struct { 13 | AccountInfo RegisterParams `json:"AccountInfo"` 14 | ID int `json:"ID"` 15 | } 16 | 17 | type ModelResp struct { 18 | ID int `json:"ID"` 19 | Model string `json:"Model"` 20 | ModelParam string `json:"ModelParam"` 21 | ModelParamInfo string `json:"ModelParamInfo"` 22 | } 23 | -------------------------------------------------------------------------------- /agentenc/__init__.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/10/27 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | from agentenc.encryptors import Encryptor, RSAEncryptor, AESEncryptor 7 | -------------------------------------------------------------------------------- /agentenc/encryptors/__init__.py: -------------------------------------------------------------------------------- 1 | from agentenc.encryptors.base import Encryptor 2 | from agentenc.encryptors.rsa import RSAEncryptor 3 | from agentenc.encryptors.aes import AESEncryptor 4 | -------------------------------------------------------------------------------- /agentenc/encryptors/aes.py: -------------------------------------------------------------------------------- 1 | from agentenc.encryptors import Encryptor 2 | from agentenc.ops import AESEncryptOp 3 | 4 | 5 | class AESEncryptor(Encryptor): 6 | def __init__(self, bits: int = 128, mode: str = 'ECB', key: bytes = None, **kwargs): 7 | """ 8 | AES 加密器 9 | 10 | :param 11 | bits(int: 128): 加密使用的 bit 数 12 | mode(str: ECB): 加密类型,可选:['ECB', 'CBC', 'CFB', 'OFB', 'CTR', 'OPENPGP', 'CCM', 'EAX', 'SIV', 'GCM', 'OCB'] 13 | iv(bytes: None): 偏移值,长度为 16 bytes ,默认随机生成 14 | key(bytes: None): AES 密钥,长度为 (bits // 8) bytes ,默认随机生成 15 | """ 16 | super(AESEncryptor, self).__init__( 17 | AESEncryptOp( 18 | bits=bits, 19 | mode=mode, 20 | key=key, 21 | **kwargs 22 | ) 23 | ) 24 | 25 | @staticmethod 26 | def decode(inp: str, key: bytes, **kwargs) -> any: 27 | """ 28 | 解密函数 29 | 30 | :param 31 | inp(str): 输入的文件路径 32 | key(bytes): AES 密钥 33 | iv(bytes): 偏移值 34 | 35 | :return 36 | pure_datas(any): 原始数据 37 | """ 38 | return Encryptor.decode( 39 | inp=inp, 40 | key=key, 41 | decode=AESEncryptOp.decode, 42 | **kwargs 43 | ) 44 | -------------------------------------------------------------------------------- /agentenc/encryptors/base.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/10/27 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | import os 6 | import json 7 | import base64 8 | import pickle 9 | 10 | from agentenc.ops import EncryptOp 11 | 12 | 13 | class Encryptor: 14 | def __init__(self, encrypt_op: EncryptOp): 15 | """ 16 | 加密器基类 17 | 18 | :param 19 | encrypt_op(EncryptOp): 加密相关OP 20 | """ 21 | self.encrypt_op = encrypt_op 22 | 23 | @staticmethod 24 | def bytes2str(input: bytes) -> str: 25 | """ 26 | bytes to base64 str (inp -> data:data/agt;base64,{base64[inp]}) 27 | 28 | :param 29 | inp(bytes): 输入 30 | 31 | :return 32 | output(str): 输出 33 | """ 34 | output = base64.b64encode(input).decode('UTF-8') 35 | return f'data:data/agt;base64,{output}' 36 | 37 | @staticmethod 38 | def str2bytes(input: str) -> bytes: 39 | """ 40 | base64 str to bytes (data:data/agt;base64,{base64[inp]} -> inp) 41 | 42 | :param 43 | inp(bytes): 输入 44 | 45 | :return 46 | output(str): 输出 47 | """ 48 | if isinstance(input, str) and input[:21] == 'data:data/agt;base64,': 49 | input = base64.b64decode(input[21:].encode('UTF-8')) 50 | assert type(input) == bytes 51 | return input 52 | 53 | @staticmethod 54 | def check_and_convert(input: any) -> any: 55 | """ 56 | 检查并递归转换 bytes -> bytes_str 57 | 58 | :param 59 | inp(any): 输入 60 | 61 | :return 62 | output(any): 输出 63 | """ 64 | if isinstance(input, dict): 65 | _input = input.copy() 66 | for k in input.keys(): 67 | _input[k] = Encryptor.check_and_convert(input[k]) 68 | return _input 69 | elif isinstance(input, (list, tuple)): 70 | _input = input.copy() 71 | for i in range(len(input)): 72 | _input[i] = Encryptor.check_and_convert(input[i]) 73 | return _input 74 | elif isinstance(input, bytes): 75 | return Encryptor.bytes2str(input) 76 | elif isinstance(input, (str, int, float, bool, None)): 77 | return input 78 | else: 79 | raise ValueError('Please check inp data type.') 80 | 81 | @staticmethod 82 | def resume_and_convert(input: any) -> any: 83 | """ 84 | 恢复并递归转换 bytes_str -> bytes 85 | 86 | :param 87 | inp(any): 输入 88 | 89 | :return 90 | output(any): 输出 91 | """ 92 | if isinstance(input, dict): 93 | for k in input.keys(): 94 | input[k] = Encryptor.resume_and_convert(input[k]) 95 | return input 96 | elif isinstance(input, (list, tuple)): 97 | for i in range(len(input)): 98 | input[i] = Encryptor.resume_and_convert(input[i]) 99 | return input 100 | elif isinstance(input, str): 101 | return Encryptor.str2bytes(input) 102 | elif isinstance(input, (int, float, bool, None)): 103 | return input 104 | else: 105 | raise ValueError('Please check inp data type.') 106 | 107 | def encode(self, inp: any, output: str, format: str = 'pkl', keys_saving_path: str = None) -> dict: 108 | """ 109 | 加密函数 110 | 111 | :param 112 | inp(any): 输入的需要加密的数据 113 | output(str): 输出的文件名称 114 | format(str: pkl [pkl / json / pdmodel]): 输出的数据格式 115 | 116 | :return 117 | private_params(dict): 加密器的私密参数,如密钥等 118 | 119 | :format details 120 | pkl: 此格式支持的加密数据类型较多,并且附带 python 解密函数,可依靠自身进行解密,但只可以在 python 端进行解密操作 121 | json: 此格式支持如下几种数据类型 (dict, list, tuple, str, int, float, bool, bytes->bytes_str, None), 可以在任意语言中读取和解密,需搭配对应语言的解密函数进行解密操作 122 | """ 123 | if format == 'pkl': 124 | encrypt_data = self.encrypt_op.encode( 125 | pickle.dumps(inp, protocol=4)) 126 | 127 | with open(output + '.pkl', "wb") as file: 128 | pickle.dump({ 129 | 'datas': Encryptor.bytes2str(encrypt_data), 130 | 'params': self.encrypt_op.get_public_params(), 131 | 'decode': self.encrypt_op.decode 132 | }, file, protocol=4) 133 | 134 | elif format == 'json': 135 | encrypt_data = self.encrypt_op.encode( 136 | json.dumps(Encryptor.check_and_convert(inp)).encode('UTF-8')) 137 | 138 | with open(output + '.json', "w") as file: 139 | json.dump({ 140 | 'datas': Encryptor.bytes2str(encrypt_data), 141 | 'params': Encryptor.check_and_convert(self.encrypt_op.get_public_params()) 142 | }, file) 143 | elif format == "pdmodel": 144 | pdiparams = inp + ".pdiparams" 145 | pdmodel = inp + ".pdmodel" 146 | assert os.path.exists(pdiparams), FileExistsError(pdiparams + "文件不存在,请检查输入路径是否正确") 147 | assert os.path.exists(pdmodel), FileExistsError(pdmodel + "文件不存在,请检查输入路径是否正确") 148 | with open(pdiparams, "rb") as f: 149 | pdiparams = f.read() 150 | with open(pdmodel, "rb") as f: 151 | pdmodel = f.read() 152 | 153 | encrypt_data = pdiparams + b"AgentEncryptionFlags" + pdmodel 154 | 155 | encrypt_data = self.encrypt_op.encode(encrypt_data) 156 | with open(output + '.EncPdModel', "wb") as file: 157 | pickle.dump({ 158 | 'data': Encryptor.bytes2str(encrypt_data), 159 | 'params': self.encrypt_op.get_public_params(), 160 | 'decode': self.encrypt_op.decode 161 | }, file, protocol=4) 162 | 163 | else: 164 | raise ValueError('Please check the format type.') 165 | 166 | return self.encrypt_op.get_private_params(keys_saving_path) 167 | 168 | @staticmethod 169 | def decode(inp: str, decode=None, **kwargs) -> any: 170 | """ 171 | 解密函数 172 | 173 | :param 174 | inp(str): 输入的文件路径 175 | decode(func): 解密函数 176 | **kwargs: 解密所需的一些其他参数 177 | 178 | :return 179 | pure_datas(any): 原始数据 180 | """ 181 | ext = os.path.splitext(inp)[1] 182 | 183 | # 加载机密数据包 184 | if ext == '.pkl' or ext == ".EncPdModel": 185 | with open(inp, "rb") as file: 186 | encrypt_package = pickle.load(file) 187 | elif ext == '.json': 188 | with open(inp, "r") as file: 189 | encrypt_package = json.load(file) 190 | else: 191 | raise ValueError('Please check inp path.') 192 | 193 | # 解码公开参数 194 | params = encrypt_package['params'] 195 | params = Encryptor.resume_and_convert(params) 196 | 197 | # 解码加密数据 198 | encrypt_data = Encryptor.str2bytes(encrypt_package['data']) 199 | decode = encrypt_package.get('decode', decode) 200 | pure_data = decode(encrypt_data, **kwargs, **params) 201 | 202 | # 重新加载原始数据 203 | if ext == '.pkl': 204 | output = pickle.loads(pure_data) 205 | elif ext == '.json': 206 | output = json.loads(pure_data.decode('UTF-8')) 207 | output = Encryptor.resume_and_convert(output) 208 | elif ext == ".EncPdModel": 209 | pdiparams, pdmodel = pure_data.split(b"AgentEncryptionFlags") 210 | from paddle.inference import Config 211 | output = Config() 212 | output.set_model_buffer(pdmodel, len(pdmodel), pdiparams, len(pdiparams)) 213 | return output 214 | else: 215 | raise ValueError('Please check inp data type.') 216 | 217 | return output 218 | -------------------------------------------------------------------------------- /agentenc/encryptors/rsa.py: -------------------------------------------------------------------------------- 1 | from agentenc.encryptors import Encryptor 2 | from agentenc.ops import RSAEncryptOp 3 | 4 | 5 | class RSAEncryptor(Encryptor): 6 | def __init__(self, bits: int = 1024, public_key: bytes = None): 7 | """ 8 | RSA 加密器 9 | 10 | :param 11 | bits(int: 1024): 加密使用的 bit 数 12 | public_key(bytes: None): RSA 公钥,格式为 b'-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY----- 的 bytes,默认随机生成 13 | """ 14 | super(RSAEncryptor, self).__init__( 15 | RSAEncryptOp( 16 | bits=bits, 17 | public_key=public_key 18 | ) 19 | ) 20 | 21 | @staticmethod 22 | def decode(inp: str, private_key: bytes) -> any: 23 | """ 24 | 解密函数 25 | 26 | :param 27 | inp(str): 输入的文件路径 28 | private_key(bytes): RSA 私钥用于数据解密 29 | 30 | :return 31 | pure_datas(any): 原始数据 32 | """ 33 | return Encryptor.decode( 34 | inp=inp, 35 | private_key=private_key, 36 | decode=RSAEncryptOp.decode 37 | ) 38 | -------------------------------------------------------------------------------- /agentenc/ops/__init__.py: -------------------------------------------------------------------------------- 1 | from agentenc.ops.base import EncryptOp 2 | from agentenc.ops.rsa import RSAEncryptOp 3 | from agentenc.ops.aes import AESEncryptOp 4 | -------------------------------------------------------------------------------- /agentenc/ops/aes.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/10/27 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | from os import urandom 7 | from Crypto.Cipher import AES 8 | 9 | from agentenc.ops import EncryptOp 10 | 11 | 12 | IV_FILE = "IV" 13 | KEY_FILE = "KEY" 14 | 15 | 16 | # AES Mode Switch 17 | ASE_MODES = { 18 | 'ECB': AES.MODE_ECB, 19 | 'CBC': AES.MODE_CBC, 20 | 'CFB': AES.MODE_CFB, 21 | 'OFB': AES.MODE_OFB, 22 | 'CTR': AES.MODE_CTR, 23 | 'CCM': AES.MODE_CCM, 24 | 'EAX': AES.MODE_EAX, 25 | 'GCM': AES.MODE_GCM, 26 | 'OCB': AES.MODE_OCB 27 | } 28 | 29 | 30 | class AESEncryptOp(EncryptOp): 31 | def __init__(self, bits: int = 128, mode: str = 'ECB', key: bytes = None, **kwargs): 32 | """ 33 | AES 加密算子 34 | 35 | :param 36 | bits(int: 128): 加密 bit 数 37 | mode(str: ECB): 加密类型,可选:['ECB', 'CBC', 'CFB', 'OFB', 'CTR', 'CCM', 'EAX', 'GCM', 'OCB'] 38 | key(bytes: None): AES 密钥,长度为 (bits // 8) bytes ,默认随机生成 39 | **kwargs: 一些其他的加密参数,如 iv, nonce 等 40 | """ 41 | super().__init__() 42 | self.length = bits // 8 43 | self.mode = mode 44 | 45 | if key is not None: 46 | self.key = key 47 | else: 48 | self.key = urandom(self.length) 49 | 50 | self.aes = AES.new( 51 | key=self.key, 52 | mode=ASE_MODES[self.mode], 53 | **kwargs 54 | ) 55 | 56 | def get_private_params(self, save_path: str = None) -> dict: 57 | """ 58 | 获取并保存密钥 59 | 60 | :param 61 | save_path(str: None): 密钥保存目录 62 | 63 | :return 64 | private_params(dict): {'key': AES 密钥} 65 | 66 | :save file details 67 | "{save_path}.key": AES 密钥 68 | """ 69 | if save_path: 70 | with open(f'{save_path}.{KEY_FILE}', "wb") as f: 71 | f.write(self.key) 72 | 73 | return { 74 | 'key': self.key 75 | } 76 | 77 | def get_public_params(self) -> dict: 78 | """ 79 | 获取解密所需的公开参数 80 | 81 | :return 82 | public_params(dict): {'mode': 加密类型} 83 | """ 84 | 85 | if hasattr(self.aes, 'iv'): 86 | return { 87 | 'mode': self.mode, 88 | 'iv': self.aes.iv 89 | } 90 | elif hasattr(self.aes, 'nonce'): 91 | return { 92 | 'mode': self.mode, 93 | 'nonce': self.aes.nonce 94 | } 95 | else: 96 | return { 97 | 'mode': self.mode 98 | } 99 | 100 | def encode(self, input: bytes) -> bytes: 101 | """ 102 | AES 加密 103 | 104 | :param 105 | inp(bytes): 输入数据 106 | 107 | :return 108 | output(bytes): 加密数据 109 | """ 110 | count = len(input) 111 | if count % self.length != 0: 112 | add = self.length - (count % self.length) 113 | else: 114 | add = 0 115 | 116 | input = input + (b'\x00' * add) 117 | output = self.aes.encrypt(input) 118 | return output 119 | 120 | @staticmethod 121 | def decode(input: bytes, mode: str, key: bytes, **kwargs) -> bytes: 122 | """ 123 | AES 解密 124 | 125 | :param 126 | inp(bytes): 加密数据 127 | mode(str): 加密类型,可选:['ECB', 'CBC', 'CFB', 'OFB', 'CTR', 'CCM', 'EAX', 'GCM', 'OCB'] 128 | key(bytes): AES 密钥 129 | **kwargs: 一些其他的加密参数,如 iv, nonce 等 130 | 131 | :return 132 | output(bytes): 原始数据 133 | """ 134 | aes = AES.new(key=key, mode=ASE_MODES[mode], **kwargs) 135 | output = aes.decrypt(input) 136 | output = output.rstrip(b'\x00') 137 | return output 138 | -------------------------------------------------------------------------------- /agentenc/ops/base.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/10/27 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | 7 | class EncryptOp: 8 | def __init__(self): 9 | """ 10 | 加密算子基类 11 | """ 12 | pass 13 | 14 | def get_private_params(self, *args, **kwargs) -> dict: 15 | """ 16 | 获取隐私参数并储存,如获取并保存密钥等信息 17 | """ 18 | pass 19 | 20 | def get_public_params(self, *args, **kwargs) -> dict: 21 | """ 22 | 客户端额外所需的解密信息,此处请勿返回任何公钥与私钥内容 23 | """ 24 | pass 25 | 26 | def encode(self, input: bytes, **kwargs) -> bytes: 27 | """ 28 | 定义加密流程 29 | """ 30 | pass 31 | 32 | @staticmethod 33 | def decode(input: bytes, **kwargs) -> bytes: 34 | """ 35 | 定义解密流程 36 | """ 37 | pass 38 | -------------------------------------------------------------------------------- /agentenc/ops/rsa.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/10/27 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | from Crypto import Random 7 | from Crypto.PublicKey import RSA 8 | from Crypto.Cipher import PKCS1_v1_5 9 | 10 | from agentenc.ops import EncryptOp 11 | 12 | 13 | PRIVATE_FILE = "PRIVATE" 14 | PUBLIC_FILE = "PUBLIC" 15 | 16 | 17 | class RSAEncryptOp(EncryptOp): 18 | def __init__(self, bits: int = 1024, public_key: bytes = None): 19 | """ 20 | RSA 加密算子 21 | 22 | :param 23 | bits(int: 1024): 加密 bit 数 24 | public_key(bytes: None): RSA 公钥,格式为 b'-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY----- 的 bytes,默认随机生成 25 | """ 26 | super().__init__() 27 | self.bits = bits 28 | 29 | if public_key is not None: 30 | self.private_key = None 31 | self.public_key = public_key 32 | else: 33 | self.rsa = RSA.generate(self.bits, Random.new().read) 34 | self.private_key = self.rsa.exportKey() 35 | self.public_key = self.rsa.publickey().exportKey() 36 | 37 | self.length = bits // 8 - 11 38 | 39 | def get_private_params(self, save_path: str = None) -> dict: 40 | """ 41 | 获取并保存密钥 42 | 43 | :param 44 | save_path(str: None): 密钥保存目录 45 | 46 | :return 47 | private_params(dict): {'private_key': RSA 私钥, 'public_key': RSA 公钥} 48 | 49 | :save file details 50 | "{save_path}.PUBLIC": RSA 公钥 51 | "{save_path}.PRIVATE": RSA 私钥 52 | """ 53 | if save_path: 54 | with open(f'{save_path}.{PUBLIC_FILE}', "wb") as f: 55 | f.write(self.public_key) 56 | 57 | if self.private_key is not None: 58 | with open(f'{save_path}.{PRIVATE_FILE}', "wb") as f: 59 | f.write(self.private_key) 60 | 61 | if self.private_key is not None: 62 | return { 63 | 'public_key': self.public_key, 64 | 'private_key': self.private_key 65 | } 66 | else: 67 | return { 68 | 'public_key': self.public_key 69 | } 70 | 71 | def get_public_params(self) -> dict: 72 | """ 73 | 获取解密所需的公开参数 74 | 75 | :return 76 | public_params(dict): {'length': 加密长度} 77 | """ 78 | return {"length": self.length + 11} 79 | 80 | def encode(self, input: bytes) -> bytes: 81 | """ 82 | RSA 加密 83 | 84 | :param 85 | inp(bytes): 输入数据 86 | 87 | :return 88 | output(bytes): 加密数据 89 | """ 90 | rsa_key = RSA.importKey(self.public_key) 91 | cipher = PKCS1_v1_5.new(rsa_key) 92 | cipher_text_ = [] 93 | 94 | for i in range(0, len(input), self.length): 95 | cipher_text_.append(cipher.encrypt(input[i:i + self.length])) 96 | output = b"" 97 | for item in cipher_text_: 98 | output += item 99 | return output 100 | 101 | @staticmethod 102 | def decode(input: bytes, length: int, private_key: bytes) -> bytes: 103 | """ 104 | RSA 解密 105 | 106 | :param 107 | inp(bytes): 加密数据 108 | length(int): 加密长度 109 | private_key(bytes): 私钥 110 | 111 | :return 112 | output(bytes): 原始数据 113 | """ 114 | rsa_key = RSA.importKey(private_key) 115 | cipher = PKCS1_v1_5.new(rsa_key) 116 | plain_text_ = [] 117 | for i in range(0, len(input), length): 118 | plain_text_.append(cipher.decrypt( 119 | input[i:i + length], "Decode error.")) 120 | output = b"" 121 | for item in plain_text_: 122 | output += item 123 | return output 124 | -------------------------------------------------------------------------------- /example/paddlepaddle/key.PRIVATE: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWwIBAAKBgQCdHPMo50Scf/K668g/kc+/rdmhbuNpe/qGH2W5xjnRimirV/59 3 | kUIv9wV3PEB71/WjNb13UcR/98Xc6+4VKD5ZsL0zW98YlflY7VjLPw5qx5egEXO1 4 | Z/ANSQxCu3fu/mi1mp69XJoPyj+bpLx5cI+RL1r/i1FqaUf+ATD6MyhaXwIDAQAB 5 | AoGAGGw1IlEc+cTr6wGW7cbRSAcS0wTlRfL3RR0hV4kIWNnOnn/9t/A6HTGlgFz1 6 | 2yp9bSL/8kncJVZTRB3KszA/zLvp+9ozoGLIGNPnyc1dAsSv6JO3cDz8pXM6jqtC 7 | ZHJ+G6vAIPITKArPyfOiCRFIrVqoWrvKG5nZG5PCV3ukYsUCQQC6z0SW3ikSnwcN 8 | u9pRmD8R1AQnT+9LQuBIq2JcBcLEFC0x/cThl7uhz+qrJSv25rfnQsaEY44oCio6 9 | KDxRWXnNAkEA103xepKUguai8GVtIrbckwgXTn3JV8uCA/WHVVrvm4CESoeMQhCJ 10 | QYgcI4s/kiql9crdyxBNXGAa2FzN3UnI2wJAJS5jxHNrUV19leoxxdO7mdzNBtYO 11 | Fri000HpTc+HuGcbp7uOmCgPHGG5n17CpV2+dLUBtg/ql2WOigzAFKDucQJAQAhT 12 | UBP2DTRQs1RG7/MYiLX4UITCc9T3lvvXwv/nkQTY012azi8i0xWK4NtSDcOXVhF+ 13 | gx0XFOkUMtLu+ugtzwJABRUvEa5vKyCqkDYiRWl+WZbm9DyOJ7NJd5Sc9dWKujeJ 14 | MJbPX6UhWeI3yn8nzTUGegECySS42vtlvHHxmu8W8g== 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /example/paddlepaddle/key.PUBLIC: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdHPMo50Scf/K668g/kc+/rdmh 3 | buNpe/qGH2W5xjnRimirV/59kUIv9wV3PEB71/WjNb13UcR/98Xc6+4VKD5ZsL0z 4 | W98YlflY7VjLPw5qx5egEXO1Z/ANSQxCu3fu/mi1mp69XJoPyj+bpLx5cI+RL1r/ 5 | i1FqaUf+ATD6MyhaXwIDAQAB 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /example/paddlepaddle/make_model.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/11/5 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | import paddle 7 | # 导入 RSA 加密器 8 | from agentenc import RSAEncryptor 9 | 10 | SAVE_ORI_MODEL_PATH = "./model/ori_model" 11 | SAVE_ENC_MODEL_PATH = "./model/enc_model" 12 | 13 | """ 14 | 制作一个简单的模型 15 | """ 16 | 17 | # 模拟一个线性层组成的模型 18 | fc = paddle.nn.Linear(1, 1) 19 | # 转静态图 20 | input_1 = paddle.static.InputSpec(shape=[-1, 1], name="input_1") 21 | # 保存模型 22 | paddle.jit.save(fc, path=SAVE_ORI_MODEL_PATH, input_spec=[input_1]) 23 | 24 | # 输入一个常量,查看结果 25 | test_ipt = paddle.to_tensor([1.], dtype="float32") 26 | out = fc(test_ipt).numpy() 27 | # 保持该结果,用于解密后的验证 28 | with open(SAVE_ENC_MODEL_PATH + "_one_test.txt", "w") as f: 29 | f.write(str(out)) 30 | print("当输入1时,程序应得到的结果为:", out) 31 | 32 | """ 33 | 加密模型 34 | """ 35 | 36 | # 初始化 RSA 加密器 37 | encryptor = RSAEncryptor(bits=1024) 38 | 39 | # 数据加密 40 | key = encryptor.encode( 41 | inp=SAVE_ORI_MODEL_PATH, 42 | output=SAVE_ENC_MODEL_PATH, 43 | format='pdmodel', 44 | keys_saving_path='key' 45 | ) 46 | print("加密完毕") 47 | -------------------------------------------------------------------------------- /example/paddlepaddle/test_model_paddleinference.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/11/5 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | import numpy as np 7 | import paddle.inference as paddle_infer 8 | from agentenc import Encryptor 9 | 10 | SAVE_ENC_MODEL_PATH = "./model/enc_model" 11 | SAVE_ENC_MODEL_FILE_PATH = SAVE_ENC_MODEL_PATH + ".EncPdModel" 12 | # 读取私钥 13 | private_key = open('key.PRIVATE', 'rb').read() 14 | 15 | # 使用解密函数对文件进行解密 16 | config = Encryptor.decode( 17 | inp=SAVE_ENC_MODEL_FILE_PATH, 18 | private_key=private_key 19 | ) 20 | 21 | # 创建 config 22 | config = paddle_infer.Config(config) 23 | 24 | # 根据 config 创建 predictor 25 | predictor = paddle_infer.create_predictor(config) 26 | 27 | # 获取输入的名称 28 | input_names = predictor.get_input_names() 29 | input_handle = predictor.get_input_handle(input_names[0]) 30 | 31 | # 设置输入 32 | fake_input = np.array([1]).astype(np.float32) 33 | input_handle.copy_from_cpu(fake_input) 34 | 35 | # 运行predictor 36 | predictor.run() 37 | 38 | # 获取输出 39 | output_names = predictor.get_output_names() 40 | output_handle = predictor.get_output_handle(output_names[0]) 41 | output_data = output_handle.copy_to_cpu() # numpy.ndarray类型 42 | print("Output data size is {}".format(output_data.size)) 43 | print("Output data shape is {}".format(output_data.shape)) 44 | 45 | """ 46 | 验证部分 47 | """ 48 | # 打开先前准备的测试结果数据 49 | with open(SAVE_ENC_MODEL_PATH + "_one_test.txt", "r") as f: 50 | one = eval(f.read()) 51 | 52 | loss = abs(output_data - one) 53 | print("LOSS:", loss) 54 | if loss < 1e-5: 55 | print("误差较低,通过测试") 56 | else: 57 | raise Exception("误差较高,请手动评估是否通过") 58 | -------------------------------------------------------------------------------- /example/paddlepaddle/test_model_ppqi.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/11/5 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | import numpy as np 7 | 8 | from ppqi import InferenceModel 9 | from agentenc import Encryptor 10 | 11 | SAVE_ENC_MODEL_PATH = "./model/enc_model" 12 | SAVE_ENC_MODEL_FILE_PATH = SAVE_ENC_MODEL_PATH + ".EncPdModel" 13 | # 读取私钥 14 | private_key = open('key.PRIVATE', 'rb').read() 15 | 16 | # 使用解密函数对文件进行解密 17 | config = Encryptor.decode( 18 | inp=SAVE_ENC_MODEL_FILE_PATH, 19 | private_key=private_key 20 | ) 21 | 22 | # 加载推理模型 23 | model = InferenceModel(config) 24 | model.eval() 25 | 26 | # 准备数据 27 | inputs = np.array([1]).astype(np.float32) 28 | 29 | # 前向计算 30 | outputs = model(inputs) 31 | 32 | """ 33 | 验证部分 34 | """ 35 | # 打开先前准备的测试结果数据 36 | with open(SAVE_ENC_MODEL_PATH + "_one_test.txt", "r") as f: 37 | one = eval(f.read()) 38 | 39 | loss = abs(outputs - one) 40 | print("LOSS:", loss) 41 | if loss < 1e-5: 42 | print("误差较低,通过测试") 43 | else: 44 | raise Exception("误差较高,请手动评估是否通过") 45 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Author: Acer Zhang 2 | # Datetime: 2021/10/27 3 | # Copyright belongs to the author. 4 | # Please indicate the source for reprinting. 5 | 6 | from setuptools import setup 7 | from setuptools import find_packages 8 | 9 | __version__ = "0.1" 10 | 11 | setup( 12 | name='AgentEnc', 13 | version=__version__, 14 | packages=['agentenc', 'agentenc.ops', 'agentenc.encryptors'], 15 | url='https://github.com/AgentMaker/AgentEncryption', 16 | license='Apache2', 17 | author='AgentMaker', 18 | author_email='agentmaker@163.com', 19 | description='飞桨模型加密库', 20 | install_requires=["ppqi", 21 | "pycryptodome"], 22 | python_requires='>3.5', 23 | include_package_data=True, 24 | ) 25 | --------------------------------------------------------------------------------