Open Hiroshiba opened 1 year ago
まず手を付け始められるのは1と、あと3もあります。 (暗号化周りはちょっとonnxruntime関係ないRust周りで困っているので、ご興味あればぜひ・・・ 😇 )
2つ目の「暗号化・復号化を組み込めるような関数を用意する」ですが、私が前試したときはまず
でlibvoicevox_decrypt.aとvoicevox_decrypt.hを作って/voicevox_decryptに突っ込み、こうやってリンクしました。
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index a5d28fb516..5582bf838f 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -966,6 +966,12 @@ function(onnxruntime_add_include_to_target dst_target)
endforeach()
endfunction()
+if(UNIX)
+ list(APPEND onnxruntime_EXTERNAL_LIBRARIES "${REPO_ROOT}/voicevox_decrypt/libvoicevox_decrypt.a")
+elseif(WIN32)
+ list(APPEND onnxruntime_EXTERNAL_LIBRARIES "${REPO_ROOT}/voicevox_decrypt/voicevox_decrypt.lib")
+endif()
+
# ACL
if (onnxruntime_USE_ACL OR onnxruntime_USE_ACL_1902 OR onnxruntime_USE_ACL_1905 OR onnxruntime_USE_ACL_1908 OR onnxruntime_USE_ACL_2002)
set(onnxruntime_USE_ACL ON)
なーーーるほどです!! 静的リンクは全く考えてませんでした。 全然知らないのですが、この関数を直に叩かれたりとか、そこのバイナリ解析されたりとかでなんか割とあっさり突破されそうなのかもとか思いました。 いやまあ、そんなこと言ってると大体どんな手法でもかなり弱い気もするのですが・・・ 😇
バイナリ解析まで視野に入れると基本的に防御は難しいと思います。推論時には復号済みのweightsがどこかに置いてある必要があり、そもそもユーザーは自分のマシンのメモリを見ることができるので 本気でやるならいわゆるアンチチートを入れることになるとおもいますが、ちょっとやりすぎな感じもあります
(バイナリ解析を妨害する技術もありますがあまり詳しくないです...)
まあそのあたりはここで議論しちゃうと・・・って感じかなと思いました。
できる範囲で考えると、暗号部分のコードやビルドコマンドを全部含めて秘匿しておいてactionsで実行、が一番強い気がしました。 となるとまあ2と3が合体した感じになるので2の工程が吹っ飛びますが。。
議題の1つに、普通のonnxモデル(OSS内にあるもの)を読めるものと、製品版のonnxモデルを読めるものとで別のdllを用意する必要があってしまうという議論がありました。 (thx. @PickledChair !)
提案されているようにonnxruntimeを使う部分も外部ライブラリとして切り出す方法があると思います。 あるいは、onnxモデルを読む関数の引数にcrepted引数を用意して制御可能にする方法もあるかなと!
このタスク、そろそろ進めたい気持ちになってきました。 以前コアをC++からRustに移行したときに @PickledChair さんが作ってくださったようなタスクリストがとりあえずあると、もう始められるなという所感です。
(時間ができたらリスト作ろうと思いますが、もしご興味ある方いたら作ってくださるとすごく嬉しいです!!!!!)
思い付くままに書いてみようとしたのですが、細かいタスクリストに落とし込む前に方針の認識合わせが必要かと思いました。方針としてはDiscordとかで話したことから次のようになるかと思っているのですが、どうでしょうか?
encrypted
引数を追加する (https://github.com/VOICEVOX/voicevox_project/issues/24#issuecomment-1485142098)1> /dev/null 2> /dev/null
の状態で .patchを適用したvoicevox_decrypt.{h,lib}をビルドして使うようにする (こけたらエスパーでなんとかする)encrypted
引数の追加)あとhttps://github.com/VOICEVOX/voicevox_core/issues/388ですが、正直VOICEVOXとしてはメリットが薄く、私個人のモチベーションに大きく左右されるかと思うので、であればここまでやってから気長にリリースという形にしたいなと思っています。
なるほどです、そんな感じで進められると良いのかなと思いました! ここから先は製品版暗号化開発チームを作ってそちらでprivateに進められると良さそうです。 (ちょっとお時間頂くかもです 🙇 )
Rust API提供タスクリスト案
こちらはこのissueと関係性が高くないので、関係性の高い https://github.com/VOICEVOX/voicevox_core/issues/388 で書くのが適当なのかなと思いました!!
APIにencrypted引数を追加する
(あまり暗号化とかに詳しくないのですが)
たとえば、ファイルの最初がVVEM
(VoiceVox Encrypted Model)で始まってたら暗号化されていると判断&復号、みたいな感じにすると引数の変更がなくなって本家の追従とかがやりやすくなると思いました。
たしかに引数がなくなると追従しやすそうですね! もし引数追加で微妙な感じになったら引数なくしても良いかもと思いました。
概要
今VOICEVOXのコードは大半がOSSですが、唯一コアのonnxモデル暗号化の部分だけがプロプライエタリになっています。 そのせいでコアはいくつかの問題が浮き彫りになっています。
特に2つ目が厄介で、Rust化してからヒホの技量不足により足を引っ張ってしまい、OSS本来の力を出せていません。
そこで生まれたのが 暗号化部分(バイナリの変換)を全部onnxruntime内に逃がす という発想です。(thx @qryxip !) これにより↑の1~4が全部解決し、特にOSS的には「専用のonnxruntimeライブラリさえ用意できればOSS版コアは独立に開発・バージョンアップできる」というかっこいい状態になります。
ちなみにキャラ追加部分は独立できないのですが、これはこちらで取り組み中です。(thx @qwerty2501 !)
手法
この「コアの製品版コードをonnxruntimeに逃がすプロジェクト」は大きく分けて3段階の工程があると思っていて、その工程ごとに人を募集したい感じです。
まず1つ目が「通常のonnxruntimeをGithub Actionsでビルドする」ことです。 Windows CPU/DirectML/CUDA、Mac CPU、Linux CPU/CUDAでのビルドが必要です。 ぶっちゃけここが一番難しい気がしています。
2つ目が「暗号化・復号化を組み込めるような関数を用意する」ことです。 これはload関数の中や外に復号化専用の経路を用意する必要があります。 ぶっちゃけここはこの発想に至ること自体は難しい一方、実装はある程度簡単な気がしています。
3つ目が製品部分、つまり暗号化・復号化処理です。 これはOSSではないため、秘匿コード開発専用のチームに参加して頂くことになります。 ここは難度が不明です。セキュリティ周り詳しい方がいたらぜひ意見聞きたいです。 成果物ができてもコードは公開できませんが、誰と一緒に作ったかはちゃんと公表させていただこうと思います。
その他
興味あれば 👀 リアクションなどいただければ・・・!
参考
Linux armhf版などのonnxruntimeをGithub Actions上でビルドしている例 https://github.com/VOICEVOX/onnxruntime-builder
Rustから直接VOICEVOX Coreを使いたい https://github.com/VOICEVOX/voicevox_core/issues/388