実現したいこと
PythonでPytorchを使って学習したモデルをonnxに変換するとき、pycryptdomeライブラリを使って暗号しました。
暗号したファイルをC++のOpenSSLライブラリを使って復号化してモデルをロードしたいのですが、うまく復号することができませんでした。復号したモデルはTensorRTでモデル変換した後、ロードする予定です。
◯python
暗号化ではpycryptdome==3.22.0を使って添付のコードのようにpytorchモデルをonnxモデルに変換しました。python側では問題なく復号化することはできました。
◯C++
OpenSSL==v3.4.1を使って添付のコードのように復号化する関数を作りました。
手探りで作ったものなので、python側の暗号化に問題があるのか・C++の復号側に問題があるのか・そもそもpythonで暗号化したものがC++で複合するのは難しいのかなど問題の特定ができていないです。
別の方法でも気密性・完全性が担保されるような方法であれば問題ないのでご享受ください。
発生している問題・分からないこと
C++の復号の関数(53行目)
EVP_CIPHER_CTX_ctr (ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), tag.data()) != 1
がfalseのため、raiseでエラー終了します。
C++でOpenSSLを使ってEER_print_errors_fp(stderr);で出力すると以下のようなエラーが出ています。
エラーメッセージ
error
1OPENSSL_Uplink(00007FFAD83F6A28,08): no OPENSSL_Applink 2
該当のソースコード
Python
1import io 2import torch 3from Crypto.Cipher import AES 4from Crypto.Protocol.KDF import PBKDF2 5from Crypto.Random import get_random_bytes 6 7def export_onnx(self, onnx_model,dummy_input, output_model_path, export_params, opset_version, do_constant_folding, input_names, output_names, dynamic_axes, verbose) : 8 9 # メモリにONNXモデルをエクスポート 10 buffer = io.BytesIO) 11 torch.onnx.export (onnx_model, 12 dummy_ input, 13 buffer, 14 export_params=export_params, 15 opset_version=opset_version, 16 do_constant_folding=do_constant_folding, 17 input_names=input_names, 18 output_names=output_names, 19 dynamic_axes=dynamic_axes, 20 verbose=verbose) 21 onnx_model_binary = buffer getvalue() 22 23 pass = "abcdefg" 24 salt = get_random_bytes(16) 25 key = PBKDF2(pass, salt, dkLen=32, count=1000000) 26 cipher = AES.new (key, AES.MODE_GCM) 27 ciphertext, tag = cipher.encrypt_and_digest(onnx_model_binary) 28 # 暗号されたデータをファイルに保存 29 with open (output_model_path, 'wb') as f: 30 f.write(salt + cipher.nonce + tag + ciphertext)
C++
1#include <openssl/evp.h> 2#include <openssl/aes.h> 3#include <openssl/err.h> 4 5std::vector<char› decryptModel(char* modelpath, std::string pass) { 6 std:: ifstream file(modelpath, std:: ios: :binary): 7 if (!file) { 8 throw std::runtime_error ("Failed to open encrypted model file."); 9 } 10 11 //ファイルから復号化に必要なデータを取得 12 std::vector <unsigned char > salt (16); 13 std::vector<unsigned char> nonce (16); 14 std::vector<unsignedchar› tag (16); 15 16 file.read (reinterpret_cast<char*>(salt.data()), salt.size()); 17 file.read (reinterpret_cast<char*>(nonce.data()), nonce.size ()); 18 file.read (reinterpret_cast<char*>(tag.data()), tag.size()); 19 20 //暗号化されたモデルデータを取得 21 std::vector<unsigned char› ciphertext ((std:: istreambuf_iterator<char›(file)), std::istreambuf_iterator<char›()); 22 file.close(); 23 24 //PBKDF2を使用してキーを取得 25 std::vector<unsigned char> key (32) ; 26 if (IPKCS5 PBKDF2_ HMAC(pass.c_str(), pass.size(), salt.data(), salt.size(), 1000000, 27 EVP_sha256(), key-size(), key .data())){ 28 throw std::runtime_error ("Failed to derive key using PBKDF2."); 29 } 30 31 // 復号化コンテキスト初期化 32 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); 33 if (!ctx) { 34 throw std::runtime error ("Failed to create EVP_CIPHER_СTX."); 35 } 36 37 if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), (), nullptr, nullptr, nullptr) != 1 || 38 EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, nonce.size(), nullptr) != 1 || 39 EVP_DecryptInit_ex(ctx, nullptr, nullptr, key.data(), nonce.data()) != 1){ 40 41 EVP_CIPHER _CTX_free (ctx) ; 42 throw std::runtime error ("Failed to initialize decrypt ion."); 43} 44 45 // モデルデータを復号化 46 std::vector<unsigned char› decrypted (ciphertext.size)); 47 int len = 0; 48 if (EVP DecryptUpdate(ctx, decrypted.data(), &len, ciphertext.data(), ciphertext.size ()) != 1) 49 { 50 EVP_CIPHER_CTX_free (ctx); 51 throw std::runtime error ("Decrypt ion failed."); 52 } 53 54 int decryptedLen = len; 55 if (EVP_CIPHER_CTX_ctr (ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), tag.data()) != 1 || 56 EVP_DecryptFinal_ex(ctx, decrypted.data() + len, &len) != 1) { 57 58 EVP_CIPHER_CTX_free (ctx); 59 throw std::runtime_error ("Decryption failed."); 60 } 61 62 decryptedLen += len; 63 decrypted.resize (decryptedLen) : 64 EVP_CIPHER_CTX_free (ctx); 65 66 //復号化されたデータからモデル情報を取得 67 std::vector<char› mode_Data(decrypted.begin(), decrypted.end ()); 68 return modelData; 69}
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
Google等で調べながら作ったコードで何が問題なのか自体が特定できていません。
補足
特になし

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。