Android 向けの .NET MAUI アプリをデバッグしていると、libEGL ログに見覚えのない他社アプリのパッケージ名がずらっと表示され、同時に javax.crypto.IllegalBlockSizeException が飛んでくることがあります。マルウェアか依存関係の混入かと不安になりますが、多くの場合は仕様と設定ミスが原因です。本記事では、この現象の正体と、例外の切り分け・解決手順を実務レベルで整理します。
症状の概要:libEGL に「知らないパッケージ名」が大量に出る
.NET MAUI(Android)アプリをデバッグしていると、Logcat に次のようなログが突然現れることがあります。
I/libEGL ( 1234): pkgname: com.smile.gifmaker
I/libEGL ( 1234): pkgname: com.tencent.mm
I/libEGL ( 1234): pkgname: com.ss.android.ugc.aweme
...
さらに、同じタイミングや直後に次のような例外が出るケースもあります。
javax.crypto.IllegalBlockSizeException:
last block incomplete in decryption
- 自分の .NET MAUI プロジェクトでは、これらのアプリを参照していない
- NuGet の参照一覧にも存在しない
- しかし毎回ログに大量に表示される
この状況は、初めて目にすると「何かが混入しているのでは?」と感じてしまいます。しかし、libEGL ログに並ぶ他社パッケージ名と、javax.crypto.IllegalBlockSizeException は根本原因が別物です。それぞれを切り分けて理解すると、不安要素がかなり減ります。
libEGL ログに出てくる他社パッケージ名の正体
libEGL と GPU ドライバの役割
libEGL は、Android 端末の GPU(グラフィック処理装置)をアプリから利用するためのライブラリです。描画の初期化やコンテキストの管理など、グラフィックス関連の土台部分を担っています。
Android 12 以降の一部端末では、アプリ起動を高速化するために、GPU ドライバ側で「人気アプリの描画情報をあらかじめ温めておく」ような最適化が行われています。その際に、端末にインストールされている(もしくは GPU ベンダがあらかじめ想定している)アプリのパッケージ名をリストアップし、libEGL のログとして出力する実装になっている機種があります。
「プリキャッシュリスト」として列挙されているだけ
つまり、ログに出てくる
- com.smile.gifmaker
- com.tencent.mm
- com.ss.android.ugc.aweme
といったパッケージ名は、GPU ドライバが持っている「描画を最適化したい・利用頻度が高いアプリ」のプリキャッシュリストであると考えて問題ありません。あなたの .NET MAUI プロジェクトに組み込まれているわけではなく、APK にも含まれていません。
イメージとしては次のような感じです。
[GPU ドライバの内部イメージ]
高速化対象のアプリ一覧:
- com.smile.gifmaker
- com.tencent.mm
- com.ss.android.ugc.aweme
- ...
アプリ起動時に、ついでにこの一覧をログに出力 →
libEGL の行として Logcat に見える
よく見かけるパッケージと意味
| パッケージ名 | 代表的なアプリ例 | 端末・自作アプリへの影響 |
|---|---|---|
| com.smile.gifmaker | 中国系ショート動画アプリ(Kuaishou 系) | インストールされていてもいなくても、ログに出るだけで APK には混入しない |
| com.tencent.mm | GPU が最適化対象として知っているだけ。あなたのアプリとは無関係 | |
| com.ss.android.ugc.aweme | TikTok / 抖音系のパッケージ | libEGL がプリキャッシュ用に参照しているだけで、バイナリには含まれない |
これらは端末ベンダ・GPU ベンダがハードウェア最適化のために扱っている情報であり、あなたが .NET MAUI で書いたアプリのコードや NuGet 参照とは別レイヤーの話です。したがって、基本的には「ノイズ」として無視して構いません。
本当に自分の APK に含まれていないか確認する方法
とはいえ、「本当に混入していないか不安」という場合は、最終 APK の中身を確認すると安心できます。
- Release ビルドで APK(または AAB)を生成する
- Android Studio の「Profile or debug APK」または「Analyze APK」を選択
- 生成された APK を開き、次のあたりをチェック
- 「lib」「assets」「res」配下に不審なファイルがないか
- META-INF や manifest に、想定外のパッケージや権限がないか
ここに、上記のような他社パッケージの AAR / JAR / SO が入っていなければ、libEGL のログは「端末側の最適化に伴う副作用としてのログ出力」と判断して問題ありません。
javax.crypto.IllegalBlockSizeException の意味と原因
例外の意味:ブロック暗号の「終わり方」が不正
一方で、javax.crypto.IllegalBlockSizeException は、Java の暗号 API を使う際に発生する例外です。典型的には、次のような状況で発生します。
- 暗号アルゴリズムがブロック暗号(例:AES/CBC、AES/ECB)である
- 復号処理で
cipher.doFinal()を呼んだとき - 入力データのサイズやパディングが、アルゴリズムの期待と合っていない
代表的なメッセージとしては、
- last block incomplete in decryption
- Input length not multiple of 16 bytes
といったものがあります。これは「暗号文の最後のブロックが 16 バイト単位になっていない」「パディングが壊れている」といった状態を示しています。
RecyclerView や .NET MAUI 本体が投げているわけではない
スタックトレースをよく見ると、IllegalBlockSizeException を投げているのは RecyclerView や .NET MAUI フレームワークそのものではなく、内部で利用されているライブラリである場合がほとんどです。
- 広告 SDK
- 解析・計測 SDK
- アプリ保護・難読化系 SDK
- 独自に組み込んだ暗号ライブラリ(Java/Kotlin 側)
これらが、設定ファイルやサーバから取得したデータを復号する際に、鍵長・IV・パディングが合っていないことで例外を出しているケースが一般的です。.NET MAUI 側で C# のコードだけを見ていても原因に辿りつけないため、「どのライブラリが暗号を使っているか」を突き止めることが重要になります。
原因と対処の整理
| 課題 | 解決策・ポイント | 補足説明 |
|---|---|---|
| libEGL ログに他社パッケージが並ぶ | GPU ドライバのアプリ起動高速化用「プリキャッシュリスト」。端末側にインストール済みまたは想定される人気アプリ名を列挙しているだけなので無視してよい。 | Android 12 以降で見られる挙動。ビルド成果物やセキュリティには直接影響しない。 |
| javax.crypto.IllegalBlockSizeException | 暗号化/復号でブロックサイズ・パディング・鍵長・IV が一致しているかを確認。内部で暗号を使う依存ライブラリ(広告 SDK 等)も疑う。 | RecyclerView 自体は暗号を使わないため、スタックトレース上の別クラスに注目する。 |
| ビルド後すぐ落ちる・再現が安定しない | bin/ と obj/ を削除してクリーンビルド。NuGet パッケージを最新に更新し、Shrink(R8/Proguard)や Linker 設定を見直す。 | 破損した中間ファイルや古い依存ライブラリが原因で例外が出るケースがある。 |
| 暗号処理を自前で実装している | 送受信側でアルゴリズム名・モード・パディングを揃える(例:AES/CBC/PKCS5Padding)。鍵長は 16/24/32 byte を厳守し、IV は毎回生成する。 | 開発中に固定 IV や適当なキーを使うと、本番のデータで復号に失敗しやすい。 |
| どこで例外が出ているか分からない | adb logcat で Crypto・Cipher・Exception をフィルタリングし、クラス名・パッケージ名から原因ライブラリを特定する。 | Android Studio の Analyze APK と併用すると、どの AAR/JAR が組み込まれているか確認しやすい。 |
.NET MAUI(Android) プロジェクトでの具体的な切り分け手順
ステップ 1:クリーンビルドで環境をリセット
まずはビルド環境のノイズを取り除きます。特に .NET MAUI は XAML ホットリロードや複数ターゲットフレームワークを多用するため、中間生成物が壊れて予期せぬ例外を引き起こすことがあります。
- プロジェクトの
bin/とobj/フォルダを手動で削除 - IDE からクリーン → 再ビルド
- CLI を使う場合は
dotnet clean dotnet build -t:Run -f net8.0-android
この段階で IllegalBlockSizeException が消える場合は、中間ファイルや古いライブラリの残骸が原因だった可能性が高いです。
ステップ 2:依存ライブラリ(NuGet / AAR)の更新
次に、依存ライブラリの更新状況を確認します。
- すべての NuGet パッケージを最新安定版へ更新
- ローカルで直接追加した AAR / JAR があれば、最新版が存在しないか確認
- 過去に導入した広告 SDK・解析 SDK で、利用していないものは参照を削除
特に広告 SDK は暗号化された設定ファイルやサーバレスポンスを扱うことが多く、バージョン mismatch による復号失敗が IllegalBlockSizeException として表に出ることがあります。
ステップ 3:ログから原因ライブラリを特定する
IllegalBlockSizeException が解消しない場合は、まず「どのパッケージが例外を出しているか」をログから読み解きます。
adb logcat | grep -i "Crypto"
adb logcat | grep -i "IllegalBlockSizeException"
出力されたスタックトレースの中から、次の情報を拾います。
- 例外を投げているクラス名(例:
com.example.sdk.crypto.AesUtil) - そのクラスが属するパッケージ(例:
com.example.sdk) - 例外を捕捉している/呼び出している場所(例:
com.example.sdk.network.ApiClient)
このパッケージ名と、プロジェクトに含まれる AAR / JAR / NuGet の中身を突き合わせることで、「どの SDK が暗号処理を行っているか」が見えてきます。
ステップ 4:Android Studio で最終 APK を調査
.NET MAUI プロジェクトであっても、最終的には通常の Android APK にパッケージングされます。これを Android Studio で開いて中身を確認します。
dotnet publish -f net8.0-android -c Releaseなどで Release ビルドを生成- 生成された APK(または AAB)を Android Studio の「Analyze APK」で開く
classes.dexやlib/配下を閲覧し、問題のパッケージ名が含まれるライブラリを特定
これにより、「この SDK が内部で javax.crypto を使っているらしい」といったヒントが得られます。
ステップ 5:自前の暗号処理がある場合のチェックポイント
もし自分で暗号処理を記述している場合、次の点を重点的に確認します。
- アルゴリズム名・モード・パディングが送信側と受信側で揃っているか
- AES の鍵長が 16/24/32 バイトのいずれかになっているか
- IV(初期化ベクタ)の長さがブロックサイズと一致しているか(AES なら 16 バイト)
- Base64 エンコード/デコード時に改行や URL-safe 形式の違いで壊れていないか
- 文字列 → バイト配列変換で文字コード(UTF-8 / UTF-16)が一致しているか
Java 側でよくあるパターンを例として示します。
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
val keySpec = SecretKeySpec(keyBytes, "AES")
val ivSpec = IvParameterSpec(ivBytes)
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec)
val decrypted = cipher.doFinal(cipherBytes)
上記で IllegalBlockSizeException が出る場合、
cipherBytesの長さが 16 の倍数になっていない- 暗号文の途中で欠損している(途中までしか受信できていない)
- 暗号化時のアルゴリズム(例:AES/GCM/NoPadding)と復号時が異なる
といった要因が考えられます。
よくある暗号周りの落とし穴と対処例
アルゴリズムとパディングの不一致
送信側と受信側で、次のような不一致があると IllegalBlockSizeException が発生します。
| 送信側 | 受信側 | 結果 |
|---|---|---|
| AES/CBC/PKCS5Padding | AES/CBC/NoPadding | 最後のブロックのパディングが解釈できず、例外になる |
| AES/GCM/NoPadding | AES/CBC/PKCS5Padding | そもそも暗号モードが違うため、ブロックサイズが合わず例外 |
| AES/ECB/PKCS5Padding | AES/CBC/PKCS5Padding | IV を前提とするかどうかが異なり、復号に失敗 |
サーバ側が何で暗号化しているか、ドキュメントや実装コードで必ず確認し、クライアント側の設定を合わせることが重要です。
鍵長・IV 長さの不正
AES の場合、鍵長は原則として
- 128bit(16 バイト)
- 192bit(24 バイト)
- 256bit(32 バイト)
のいずれかです。中途半端な長さの byte[] をそのまま SecretKeySpec に渡していると、内部で例外が発生する可能性があります。
また、IV の長さもブロックサイズと一致している必要があります。AES なら 16 バイトでなければなりません。IV を文字列のまま送受信していると、文字コードや Base64 の扱いによって長さが変わってしまうことがあるため注意が必要です。
Base64 の扱いミス
暗号文を文字列に変換する際、多くの実装が Base64 を利用しますが、
- URL-safe Base64 と通常の Base64 を混在させている
- 「=」によるパディングを削除してしまっている
- 改行コード付きのエンコードを使用している
といった差異により、復号時に元のバイト列が復元できなくなり、結果として IllegalBlockSizeException が発生することがあります。
Java では Base64.getDecoder()、C# では Convert.FromBase64String などを用い、双方で実装と設定を合わせておくことが重要です。
通信エラーによる暗号文の欠損
ネットワーク通信中に暗号文が途中で欠損すると、受信側で復号を試みた際に最後のブロックが足りず IllegalBlockSizeException が発生します。この場合、
- レスポンスの長さをログに出す
- 送信前後でハッシュ値を比較する
- HTTP ステータスコードやエラーメッセージを併せて確認する
といった手法で、「暗号の設定問題」なのか「通信路の問題」なのかを切り分けることができます。
libEGL のパッケージ列挙をどこまで気にすべきか
セキュリティリスクではない理由
libEGL のログに他社パッケージ名が列挙される挙動は、あくまで GPU ドライバ側の実装に由来します。あなたの .NET MAUI アプリが、これらのアプリをバンドルしていたり、勝手に連携していたりするわけではありません。
ポイントをまとめると次の通りです。
- ログに表示されるだけで、APK に他社アプリが含まれるわけではない
- libEGL が GPU 最適化のために持っている「候補リスト」を吐き出しているだけ
- セキュリティリスクやストア審査への直接的な影響はない
そのため、IllegalBlockSizeException のような実際の例外とは切り離して考えるべきです。エラー解析の際は、libEGL ログをノイズとして扱い、例外スタックトレース側に集中するのが効率的です。
ログを読みやすくする小技
Logcat を見る際に、libEGL のログが多すぎて邪魔な場合は、フィルタ機能を使って自分のアプリのタグやプロセスだけに絞ると解析が楽になります。
- Android Studio の Logcat で、アプリプロセスを選択する
- 「Regex」をオンにして、
^(?!.*libEGL).*のような除外フィルタを試す - 自前のログ出力に一貫したタグ(例:
MyApp)を付け、tag:MyAppで絞り込む
これにより、GPU ドライバ由来のログに気を取られず、本当に見るべき例外や警告に集中できます。
実務で使える「最短コース」チェックリスト
最後に、今回のような症状が出たときに、短時間で原因を絞り込むためのチェックリストをまとめます。
| 手順 | 内容 | ポイント |
|---|---|---|
| 1. クリーンビルド | bin/ と obj/ を削除し、dotnet clean → dotnet build を実行 | 中間生成物の破損や古い DLL による不具合を除外する |
| 2. 依存ライブラリ更新 | NuGet パッケージと組み込み AAR/JAR を最新版へ更新し、不要なものは消す | 特に広告・解析 SDK は暗号を内部利用しやすく、バージョン mismatch で例外になりがち |
| 3. 暗号処理の見直し | 自前実装がある場合、アルゴリズム・鍵長・IV・Base64・文字コードを総点検 | 送受信側で設定を揃え、固定 IV やテスト用キーを本番に残さない |
| 4. 動的解析 | adb logcat で Crypto 関連ログをフィルタし、スタックトレースから原因クラスを特定 | libEGL ログはノイズと割り切り、例外の行に注目する |
| 5. APK の静的解析 | Android Studio の Analyze APK で最終バイナリを開き、想定外のライブラリがないか確認 | 必要のない SDK は .csproj の ItemGroup から Remove し、バイナリサイズも削減できる |
これらを一通り実施すれば、多くのケースで IllegalBlockSizeException の原因は特定できます。そして、libEGL の他社パッケージ名については、「Android 12 以降の GPU ドライバが勝手に出しているプリキャッシュリストに過ぎない」と理解しておけば、ログを眺めるたびに不安になることもなくなるはずです。
.NET MAUI はマルチプラットフォームゆえにトラブルシュートが難しく感じられますが、Android ネイティブの挙動とフレームワークの挙動を分けて考えることで、問題の切り分けはぐっと楽になります。libEGL ログは「背景ノイズ」、IllegalBlockSizeException は「実際のエラー」として意識的に分離し、落ち着いてスタックトレースと依存関係を確認していきましょう。

コメント