この記事はAIによって生成されたコンテンツを含みます。(スクショ、コマンド出力、ログ、トレースなどには含みません)
はじめに
現代のソフトウェア開発において、暗号技術は信頼性と安全性を支える基盤です。しかし、暗号アルゴリズムや鍵管理の不備は重大なセキュリティー・リスクを引き起こし、量子コンピューターの進展によりその脅威はさらに高まっています。このような背景から、暗号資産の可視化と標準化は急務となっています。
Cryptographic Bill of Materials (CBOM) は、ソフトウェアに含まれる暗号アルゴリズム、鍵、証明書、プロトコルなどを体系的に記録する仕組みであり、Linux Foundationの Post-Quantum Cryptography Alliance (PQCA) によって標準化が進められています。この取り組みを加速するため、IBMは CBOM関連ツール群をLinux Foundationに寄贈しました。その一翼を担うのが Sonar-cryptographyプラグインで、JavaやPythonのソースコードを解析し、暗号資産をCBOM形式で出力します。
本記事では、SonarQubeとSonar-cryptographyプラグインを用いてJavaコードから暗号資産を検出し、CBOMを生成する方法を紹介します。
Sonar-cryptographyプラグインのセットアップ
Sonar-cryptographyの利用には SonarQubeサーバーのセットアップが必要です。SonarQubeは無料で利用できますが、エディションによって機能が異なります。
今回利用する Community Edition は、Java、JavaScript、Pythonなど主要言語の静的解析が可能で、基本的なコード品質チェック機能を提供しています。個人や小規模チームでの利用には十分な機能があり、SonarQubeの公式サイトからダウンロードしてインストールできます。
Sonar-cryptographyプラグイン (執筆時v1.4.8) をSonarQubeで使用するための要件は、SonarQube 9.9 (LTS) 以降です。
SonarQube Community Edition は Dockerでも使用可能であり、公式イメージを使用すれば、インストール作業を省略してすぐに使い始めることができます。
Docker composeでSonarQubeを起動する
本番環境では PostgreSQL などの外部データベースの使用が推奨されていますが、評価・テスト目的であれば、embedded H2 database を使って起動することができます。
以下は、embedded H2 database を使った最小構成の docker-compose.yml の例です。
version: '3'
services:
sonarqube:
image: sonarqube:community
container_name: sonarqube
ports:
- "9000:9000"
environment:
- SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
volumes:
- ./sonarqube_data:/opt/sonarqube/data
- ./sonarqube_extensions:/opt/sonarqube/extensions
- ./sonarqube_logs:/opt/sonarqube/logs
任意のフォルダーを作成し、上記のdocker-compose.ymlを配置します。
永続化したいデータのために、sonarqube_data、sonarqube_extensions、sonarqube_logsフォルダーを作成し、docker compose up -dコマンドで起動します。
ブラウザーで http://<your-sonarqube-host>:9000 にアクセスすると、ログイン画面が表示されますので、初期ログイン情報 (admin/admin) を使ってログインし、パスワードを変更してください。
Sonar-cryptographyプラグインの入手と組み込み
Sonar-cryptographyプラグインのjarファイルは、https://github.com/PQCA/sonar-cryptography/releases にアクセスして最新のリリース (執筆時は 1.4.8) を選択し、「Assets」セクションにあるcom.ibm.sonar-cryptography-plugin-<version>.jarを選択するとダウンロードできます。
少々わかりにくいですのでスクショを貼っておきますが、右側の「Assets」の下に並んでいるハイパーリンクをクリックすると、ダウンロードが始まります。
Sonar-cryptographyプラグインをSonarQubeで使用するためには、コンテナー内の /opt/sonarqube/extensions/plugins/ に jarファイルを配置して、SonarQube を再起動します。
前述のdocker-compose.ymlの場合、コンテナー内のパスはホスト側のsonarqube_extensionsにマッピングされていますので、さらにpluginsフォルダーを作成して、その中に jarファイルを置きます。
プラグインが正しく読み込まれたかどうかは、SonarQubeのUIから確認できます。
-
http://<your-sonarqube-host>:9000にアクセスし、管理者アカウントでログインします。 -
上部のタブから「Administration」→「Marketplace」→「Plugins」の順に遷移します。
-
「Installed」を選択したリストに、「Sonar Crypto Plugin」が含まれていることを確認してください。
ここまでのインストール作業で、docker-compose.ymlを配置したフォルダーは以下のような構造になっています。(抜粋)
.:
合計 16
-rw-r--r-- 1 khirazo khirazo 353 12月 2 14:40 docker-compose.yml
drwxr-xr-x 4 khirazo khirazo 4096 12月 2 14:42 sonarqube_data
drwxr-xr-x 4 khirazo khirazo 4096 12月 2 14:42 sonarqube_extensions
drwxr-xr-x 2 khirazo khirazo 4096 12月 8 10:46 sonarqube_logs
./sonarqube_extensions:
合計 8
drwxr-xr-x 2 khirazo root 4096 12月 2 14:42 downloads
drwxr-xr-x 2 khirazo khirazo 4096 12月 2 14:30 plugins
./sonarqube_extensions/plugins:
合計 33124
-rw-r--r-- 1 khirazo khirazo 33916166 12月 2 14:23 sonar-cryptography-plugin-1.4.8.jar
SonarQubeでルールを有効化する
プラグインは、SonarQubeに認識されただけではスキャンに使用されません。SonarQubeでルールを有効化するには、「Quality Profile」を編集します。
-
SonarQube UIに管理者権限でログインし、「Quality Profiles」タブを選択します。
-
今回はJavaコードですので、「Java」のプロファイルを選択します。
-
デフォルトの「Sonar way」では「Activate More」がグレーアウトされていてルールを追加できないので、カスタムプロファイルを作成します。
「Sonar way」を開いて「⋮」メニューから「Extend」を選択すると、任意のプロファイルを作成できます。
以下の例では、「CBOM Generation」という名前のプロファイルを作成済みです。 -
作成したカスタムプロファイルの右下にある「Activate More」をクリックし、「Cryptographic Inventory (CBOM)」を探してクリックします。(Java用とPython用があります)
開いた画面に「Activate」ボタンがありますので、クリックして紐づけます。
後述しますが、スキャンする前に、このプロファイルをプロジェクトに関連付ける必要があります。
Javaソースコードのスキャン
SonarQubeでJavaのソースコードをスキャンするには、以下の手順を実施します。
-
プロジェクトを作成し、トークンを生成します。
-
公式ページからダウンロードしたSonarScannerをインストールし、環境変数 PATH に追加します。
ガイド等ではMavenやGradleがよく出てきますが、今回はSonarScanner CLIを使用します。 -
Javaプロジェクトのルートに
sonar-project.propertiesを作成します。 -
Javaの場合、コンパイル後にスキャンする必要がありますので、ビルドしていない場合はビルドします。
SonarScanner CLIを使えば、MavenやGradleなしでもJavaコードをスキャンできます。 -
スキャンの結果を確認します。
一般的にはSonarQube UIでプロジェクトを開いて確認すると思いますが、今回の目的であるSonar-cryptographyプラグインは、Javaプロジェクトのフォルダーにcbom.jsonというファイルを出力します。
実は、SonarScanner CLIについても、インストールせずにDockerで実行できます。
そこで、今回はDockerから呼び出す形でスキャンを行いたいと思います。
プロジェクトの作成とセットアップ
SonarQubeプロジェクトの作成と関連作業
SonarQubeのプロジェクトは、「Projects」タブの「Create Project」から作成します。今回はLocal projectで、名前は「My Java Project」にしました。
スキャン対象のJavaソースコードが手もとにない場合は、任意のオープンソースプロジェクト(チャットアプリなど暗号機能を持つもの)を利用するとよいでしょう。
プロジェクトを作成すると、トークンを生成できるようになります。画面の下部にある「How do you want to analyze your repository?」部分で「Locally」を選択し、「Provide a token」部分で「Generate」をクリックします。生成されたトークンはどこかにメモしておいてください。
また、先ほど作成したカスタムプロファイルを、このプロジェクトに紐づけておきます。
「Projects」タブで対象のプロジェクトを選択し、「Project Settings」→「Quality Profiles」を選びます。「Add a language」画面でJavaを選択し、プロファイルとして先ほど作成した「CBOM Generation」を選択します。
sonar-project.propertiesの作成
スキャン対象のJavaソースコードが置かれているフォルダーのルートに sonar-project.properties を作成し、作成したプロジェクトの情報を記述します。
今回は以下の定義を使用します。(トークンには正しい値を指定します)
sonar.projectKey=my-java-project
sonar.projectName=My Java Project
sonar.projectVersion=1.0
sonar.sources=src
sonar.java.binaries=build
sonar.host.url=http://localhost:9000
sonar.token=<your_token>
この例の場合、srcにソースコードが、buildにビルド後の classファイルが置かれています。
スキャンの実施
これで準備が整いましたので、スキャンを行ってみたいと思います。
コマンドプロンプト (今回はWSL環境)を開いて、カレントフォルダーを対象のJavaプロジェクトに設定し、SonarScanner CLIをDocker経由で呼び出します。
docker run --rm \
-e SONAR_HOST_URL="http://host.docker.internal:9000" \
-e SONAR_LOGIN="<your_token>" \
-v $(pwd):/usr/src \
sonarsource/sonar-scanner-cli
この記事の検証環境は、サーバーが同じマシンのdocker compose で起動していたので、 クライアント側を docker run で起動した場合に、localhost宛では接続できませんでした。host.docker.internal を指定することで接続できましたが、OS環境によってはネットワークの定義を工夫する必要があるかもしれません。
以下は、スキャン時にコマンドラインに表示されたログの抜粋です。
06:58:02.827 INFO Scanner configuration file: /opt/sonar-scanner/conf/sonar-scanner.properties
06:58:02.835 INFO Project . configuration file: /usr/src/sonar-project.properties
06:58:02.880 INFO SonarScanner CLI 7.3.0.5189
06:58:02.882 INFO Linux 6.6.87.2-microsoft-standard-WSL2 amd64
06:58:04.427 INFO Communicating with SonarQube Community Build 25.10.0.114319
06:58:04.428 INFO JRE provisioning: os[linux], arch[x86_64]
06:58:06.691 INFO Starting SonarScanner Engine...
06:58:06.691 INFO Java 17.0.13 Eclipse Adoptium (64-bit)
06:58:05.704 INFO Load global settings
06:58:05.793 INFO Load global settings (done) | time=90ms
06:58:05.796 INFO Server id: 147B411E-AZrdlS-8U3JK0eKGSgJ_
06:58:05.825 INFO Loading required plugins
06:58:05.826 INFO Load plugins index
06:58:05.847 INFO Load plugins index (done) | time=21ms
06:58:05.847 INFO Load/download plugins
06:58:06.354 INFO Load/download plugins (done) | time=507ms
06:58:06.734 INFO Process project properties
06:58:06.750 INFO Process project properties (done) | time=16ms
06:58:06.785 INFO Project key: my-java-project
06:58:06.786 INFO Base dir: /usr/src
06:58:06.787 INFO Working dir: /tmp/.scannerwork
06:58:06.804 INFO Load project settings for component key: 'my-java-project'
06:58:06.826 INFO Load project settings for component key: 'my-java-project' (done) | time=23ms
06:58:06.858 INFO Load quality profiles
06:58:06.942 INFO Load quality profiles (done) | time=84ms
06:58:07.015 INFO Load active rules
06:58:07.463 INFO Load active rules (done) | time=447ms
06:58:07.475 INFO Load analysis cache
06:58:07.526 INFO Load analysis cache (794 bytes) | time=51ms
06:58:07.633 INFO Preprocessing files...
06:58:09.128 INFO 1 language detected in 18 preprocessed files (done) | time=1494ms
06:58:09.129 INFO 0 files ignored because of scm ignore settings
06:58:09.130 INFO Loading plugins for detected languages
06:58:09.131 INFO Load/download plugins
06:58:09.709 INFO Load/download plugins (done) | time=578ms
06:58:09.775 INFO Sonar Cryptography initialized in context (SONARQUBE)
06:58:09.844 INFO Load project repositories
06:58:09.943 INFO Load project repositories (done) | time=99ms
06:58:09.961 INFO Indexing files...
06:58:09.962 INFO Project configuration:
06:58:10.068 INFO 18 files indexed (done) | time=107ms
06:58:10.070 INFO Quality profile for java: CBOM Generation
06:58:10.072 INFO ------------- Run sensors on module My Java Project
06:58:10.096 INFO Sonar Cryptography initialized in context (SONARQUBE)
06:58:10.140 INFO Load metrics repository
06:58:10.162 INFO Load metrics repository (done) | time=21ms
06:58:12.180 INFO Sensor JavaSensor [java]
06:58:12.211 INFO Server-side caching is enabled. The Java analyzer will not try to leverage data from a previous analysis.
06:58:12.213 INFO Using ECJ batch to parse 15 Main java source files with batch size 204 KB.
06:58:13.069 INFO Starting batch processing.
06:58:13.672 INFO The Java analyzer cannot skip unchanged files in this context. A full analysis is performed for all files.
06:58:15.308 INFO Detected (BlockCipher) AES128-ECB-PKCS5
06:58:17.765 INFO Detected (Key) RSA
06:58:17.920 INFO Detected (Signature) MD5withRSA
06:58:17.981 INFO Detected (PublicKeyEncryption) RSA-2048
06:58:18.658 INFO Detected (Key) RSA
06:58:18.686 INFO Detected (SecretKey) AES
06:58:18.727 INFO Detected (SecretKey) DES
06:58:18.841 INFO Detected (Signature) MD5withRSA
06:58:18.915 INFO Detected (PublicKeyEncryption) RSA-2048
06:58:18.926 INFO Detected (SecretKey) AES
06:58:19.004 INFO Detected (PublicKeyEncryption) RSA-2048
06:58:19.043 INFO Detected (Signature) MD5withRSA
06:58:19.080 INFO 100% analyzed
06:58:19.081 INFO Batch processing: Done.
(中略)
06:58:21.391 INFO Executing post-job 'Output generation'
06:58:21.676 INFO CBOM was successfully generated '/usr/src/cbom.json'.
06:58:21.678 INFO ========== CBOM Statistics ==========
06:58:21.678 INFO Detected Assets : 12
06:58:21.679 INFO - Key : 2
06:58:21.679 INFO - BlockCipher : 1
06:58:21.679 INFO - SecretKey : 3
06:58:21.680 INFO - Signature : 3
06:58:21.680 INFO - PublicKeyEncryption : 3
06:58:21.680 INFO =====================================
06:58:21.691 INFO Analysis total time: 15.251 s
06:58:21.691 INFO SonarScanner Engine completed successfully
06:58:21.931 INFO EXECUTION SUCCESS
06:58:21.933 INFO Total time: 19.113s
生成されたCBOMの確認
以下に、生成されたCBOMの例を示します。一部の値はダミーに置き換えています。
{
"bomFormat" : "CycloneDX",
"specVersion" : "1.6",
"serialNumber" : "urn:uuid:21f02bce-eff3-41bf-a127-11e18f985f0a",
"version" : 1,
"metadata" : {
"timestamp" : "2025-12-02T06:58:21Z",
"tools" : {
"components" : [ ],
"services" : [
{
"provider" : {
"name" : "IBM"
},
"name" : "Sonar Cryptography Plugin",
"version" : "1.4.8"
}
]
}
},
"components" : [
{
"type" : "cryptographic-asset",
"bom-ref" : "8827fa02-9a1e-4574-b648-8af5c51b43d1",
"name" : "AES128-ECB-PKCS5",
"evidence" : {
"occurrences" : [
{
"location" : "src/Client/Encryption/AES.java",
"line" : 118,
"offset" : 24,
"additionalContext" : "javax.crypto.Cipher#getInstance(Ljava/lang/String;)Ljavax/crypto/Cipher;"
}
]
},
"cryptoProperties" : {
"assetType" : "algorithm",
"algorithmProperties" : {
"primitive" : "block-cipher",
"parameterSetIdentifier" : "128",
"mode" : "ecb",
"padding" : "pkcs5",
"cryptoFunctions" : [
"encrypt"
]
},
"oid" : "2.16.840.1.101.3.4.1"
}
},
{
"type" : "cryptographic-asset",
"bom-ref" : "7a35f622-ff18-41cf-83f7-20e0fd100c74",
"name" : "MD5withRSA",
"evidence" : {
"occurrences" : [
{
"location" : "src/Decrypt.java",
"line" : 115,
"offset" : 19,
"additionalContext" : "java.security.Signature#getInstance(Ljava/lang/String;)Ljava/security/Signature;"
},
{
"location" : "src/Client/Encryption/Decrypt.java",
"line" : 115,
"offset" : 19,
"additionalContext" : "java.security.Signature#getInstance(Ljava/lang/String;)Ljava/security/Signature;"
},
{
"location" : "src/Encrypt.java",
"line" : 124,
"offset" : 24,
"additionalContext" : "java.security.Signature#getInstance(Ljava/lang/String;)Ljava/security/Signature;"
}
]
},
"cryptoProperties" : {
"assetType" : "algorithm",
"algorithmProperties" : {
"primitive" : "signature",
"parameterSetIdentifier" : "2048",
"cryptoFunctions" : [
"verify"
]
},
"oid" : "1.2.840.113549.1.1.4"
}
}
]
}
以下に、各CBOMフィールドの簡単な説明を記します。
| フィールド名 | 説明 |
|---|---|
| bomFormat | CBOMのフォーマット(例:CycloneDX) |
| specVersion | 使用している仕様のバージョン番号 |
| serialNumber | BOMの一意な識別子(UUID形式) |
| version | BOMのバージョン番号 |
| metadata | メタデータ全体を保持するオブジェクト |
| timestamp | BOMが生成された日時 |
| tools | BOM生成に使用したツール情報 |
| components | ソフトウェアコンポーネント情報 |
| services | 関連するサービス情報 |
| provider.name | BOM提供者の名前 |
| components | |
| type | コンポーネントの種類(例:cryptographic-asset) |
| bom-ref | コンポーネントの参照ID |
| name | 暗号資産の名前(例:AES128-ECB-PKCS5) |
| evidence | |
| occurrences.location | 該当暗号資産が検出されたソースコードの場所 |
| occurrences.line | 該当箇所の行番号 |
| occurrences.offset | 該当箇所のオフセット位置 |
| additionalContext | 検出に関する追加情報(API呼び出しなど) |
| cryptoProperties | |
| assetType | 暗号資産の種類(例:algorithm、secret-key) |
| algorithmProperties | アルゴリズムの詳細情報(例:ブロック暗号、パラメータセット) |
| parameterSetIdentifier | パラメータセットの識別子(例:128、2048) |
| mode | 暗号モード(例:ECB、GCM) |
| padding | パディング方式(例:PKCS5) |
| cryptoFunctions | 暗号機能(例:encrypt、keygen、verify) |
| oid | オブジェクト識別子(OID) |
CBOMは人間が直接読むことを前提としたものではなく、ツールやプロセスに組み込んで活用することが想定されています。CBOMはCycloneDX仕様に準拠した構造化データなので、専用ツールで読み込むことで、暗号資産の一覧や依存関係を可視化できます。
例えば、CBOMkitサイト上には、JSONファイルをアップロードすることで、CBOMを可視化できるサービスがあります。
ただ、CBOMは暗号情報が記されたファイルですので、見知らぬサーバーにアップロードすることは避けて、管理の行き届いた環境でcbomkitに含まれるCBOM Viewerなどを利用するほうがよいでしょう。
まとめ
本記事では、SonarQubeとSonar-cryptographyプラグインを用いて、Javaソースコードから暗号資産を検出し、CBOMを生成する手順を紹介しました。Docker ComposeによるSonarQube環境構築、プラグインの組み込み、ルールの有効化、そしてSonarScannerによるスキャンまでを一通り実施し、CBOMの構造と用途についても解説しました。
CBOMは人間が直接読むことを目的としたものではなく、セキュリティー評価やコンプライアンス対応、量子安全性移行計画の基盤として、ツールやプロセスに組み込んで活用することが想定されています。今回の手法をCI/CDパイプラインに統合すれば、暗号資産の棚卸しを自動化し、リスク管理を継続的に行うことができます。
現在のところSonar-cryptographyプラグインは、JavaのJCAとBouncyCastle、および Pythonのpyca/cryptographyに対応しています。もしそれで足りない場合は、商用製品も検討してみてください。例えば、IBM Quantum Safe Explorerは、執筆時点で C、C++、C#、Dart、Go、Java、Pythonに対応しており、JavaとPythonについても、Sonar-cryptographyプラグインよりも多くのライブラリーに対応しています。
また、CBOMは暗号アルゴリズムや鍵の強度をチェックしたり脆弱な設定を検出したりするものではなく、暗号の使用箇所を見つけてくれるものです。前述のCBOM Viewerのスクリーンショットにコンプライアンス・チェック結果のようなものが含まれていますが、それはあくまでもCBOMを解釈する側の機能となります。このあたりについても、商用製品では脆弱性診断を含めた機能(例えばCWE-327の検出など)を持っている場合がありますので、目的に応じてツールを使い分けるとよいでしょう。





