【入門編】Maven/Gradleでビルド結果を署名・検証せよ!成果物の改ざんを防ぐCode Signing実装術 – ビルド・パッケージ管理ツール生産性向上バイブル

こんにちは!開発現場を支えるインフラやビルド周りの仕組み、奥が深くて面白いですよね。

今回は、Javaの世界で避けて通れないけれど、初学者のうちは「なんだか難しそう…」とスルーしがちな「ビルド成果物のGPG署名と検証(Code Signing)」をテーマに取って上げます。

「公開用ライブラリなんてまだ作らないよ」と思うかもしれませんが、企業内でのプライベートリポジトリ運用や、サプライチェーン攻撃(依存関係の乗っ取り)が現実の脅威となっている現代において、「自分がビルドした成果物が、誰にも改ざんされていない正当なものである」と暗号学的に証明できる技術は、シニアエンジニアへの第一歩として絶対に知っておくべき必須教養です。

これをマスターすれば、CI/CDパイプラインの信頼性が劇的に跳ね上がり、チーム全体のセキュリティ意識も底上げされますよ。さあ、一緒に深掘りしていきましょう!

—

1. なぜ「署名」が必要なのか?(技術の本質を知る)

私たちが日常的に使っているMavenやGradleは、リモートリポジトリ(Maven Centralや内部のNexus/Artifactoryなど)からjarファイルをダウンロードしてきます。

もし、その途中の通信経路やストレージが攻撃者に侵入されたらどうなるでしょうか? 悪意ある第三者がクラスファイルをこっそり書き換え、パスワードを盗み出すコードを混入させても、私たちは気づかずにそれをプロダクション環境にデプロイしてしまう危険性があります。

ここで登場するのが GPG(GNU Privacy Guard) を使った「デジタル署名」です。

1. 秘密鍵(Private Key)でハッシュ値に署名: 開発者(またはCI/CDサーバー)の手元で成果物(`.jar`や`.pom`)のハッシュ値を計算し、秘密鍵で暗号化して「`.asc`」という署名ファイルを生成します。
2. 公開鍵(Public Key)で検証: 利用者やリポジトリ側は、あなたの公開鍵を使って署名を復元し、成果物が改ざんされていないか、本当にあなたが作ったものかを数学的に検証します。

この仕組みがあるおかげで、「誰が作ったか(認証)」と「途中でいじられていないか(完全性)」が完全に担保されるのです。

—

2. 基礎準備:GPG鍵ペアの生成と環境構築

まずは、あなたのマシン上で署名を行うための「鍵ペア(秘密鍵と公開鍵)」を作成します。すでに持っている方はこのステップをスキップしても構いませんが、新規作成の手順をサクッと見ておきましょう。

ターミナルを開き、以下のコマンドを実行します。

対話形式でGPG鍵を生成します
gpg –full-generate-key

実行すると、いくつか質問されます。実務の標準的なおすすめ設定は以下の通りです。

  • Key type: `1` (RSA and RSA – デフォルト)
  • Key length: `4096` (セキュリティ強度を高めるため4096ビット推奨)
  • Expiration: `0` (無期限、または運用ポリシーに合わせた有効期限)
  • Real name / Email: あなたの本名と、GitHub等に紐づくメールアドレスを入力。

鍵が生成できたら、自分の鍵ID(フィンガープリント)を確認します。

秘密鍵・公開鍵のリストを表示
gpg –list-secret-keys –keyid-format LONG

出力結果の `sec rsa4096/XXXXXXXXX 202X-XX-XX […]` の `XXXXXXXXX` の部分があなたの「Key ID」です。これをメモしておいてください。

—

3. Mavenでの実装:`maven-gpg-plugin` の設定

それでは、Mavenプロジェクトでビルド時に自動で署名を行う設定をしていきましょう。
Mavenでは、`pom.xml` の `build/plugins` セクション、あるいはリリース時のみ有効にするために `profile` セクションに設定を記述します。

実践 `pom.xml` 設定例


4.0.0

com.example
my-secure-library
1.0.0 jar

org.apache.maven.plugins
maven-compiler-plugin
3.11.0
17
17

org.apache.maven.plugins
maven-gpg-plugin
3.1


sign-artifacts
verify
sign






–pinentry-mode
loopback

Mavenでの動作確認コマンド

設定が終わったら、以下のコマンドでビルドと署名の生成をテストしてみましょう。

verifyフェーズまでを実行(コンパイル、テスト、パッケージ、そして署名が行われる)
mvn clean verify

成功すると、`target/` ディレクトリの中に通常の `my-secure-library-1.0.0.jar` に加えて、`my-secure-library-1.0.0.jar.asc` という署名ファイルが生成されているはずです!これが、改ざんを防ぐための魔法の切符となります。

—

4. Gradleでの実装:`signing` プラグインの設定

次に、モダンなJavaプロジェクトで主流となっているGradleでの設定方法を解説します。
Gradleには、公式で非常に使いやすい `signing` プラグインが用意されています。

実践 `build.gradle` 設定例

プロジェクトの `build.gradle` に以下のように記述します。

plugins {
id ‘java’
// 成果物署名のための公式プラグインを有効化
id ‘signing’
id ‘maven-publish’ // リポジトリへの公開準備用
}

group = ‘com.example’
version = ‘1.0.0’

repositories {
mavenCentral()
}

java {
// ソースコードとJavadocのjarも一緒に生成する(公開用ライブラリの基本)
withJavadocJar()
withSourcesJar()
}

// 署名プラグインの設定
signing {
// 秘匿情報を環境変数から取得するようにマッピング
def signingKey = System.getenv(“SIGNING_KEY”) // 秘密鍵(ASCII Armor形式)
def signingPassword = System.getenv(“SIGNING_PASSWORD”) // 秘密鍵のパスフレーズ

// メモリ上の秘密鍵を使って署名を行う(ファイルパスを指定せず安全)
useInMemoryPgpKeys(signingKey, signingPassword)

// javaプラットフォームによって生成されるすべての成果物(jar, sources, javadoc, pom)を一括署名対象にする
sign publishing.publications
}

// Maven形式でのパブリッシュ設定(ローカルテスト用)
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}

Gradleでの動作確認コマンド

Gradleで署名を含めたビルド(タスク実行)を行うには、以下のコマンドを叩きます。

maven-publishの成果物生成と署名を同時に実行
gradle signMavenJavaPublication

環境変数 `SIGNING_KEY` と `SIGNING_PASSWORD` がローカルに設定されていない場合はエラーになりますが、次で解説するCI/CD環境ではこのメモリ上からの読み込み方式が最強の武器になります。

—

5. CI/CD環境(GitHub Actions等)での秘密鍵管理ベストプラクティス

ローカル開発環境で署名ができるようになったら、次は「GitHub ActionsなどのCI/CDパイプライン上で、どう安全に秘密鍵を扱うか」という実務の壁にぶつかります。

サーバー上に秘密鍵のファイルを丸ごと置くのは、セキュリティインシデントの元です。ここで、先ほどのGradleでも紹介した「環境変数(Secrets)へのインメモリ渡し」の出番となります。

ステップ1: 秘密鍵をBase64エンコードする

ローカルのターミナルで、自分の秘密鍵をBase64文字列に変換します(改行コードの化けを防ぐため)。

秘密鍵をエクスポートしてBase64にエンコード(YOUR_KEY_IDは自身のIDに置き換え)
gpg –export-secret-keys –armor YOUR_KEY_ID | base64

出力された長ーーい文字列をコピーします。

ステップ2: GitHubの Secrets に登録する

GitHubリポジトリの `Settings > Secrets and variables > Actions` から、以下の2つを登録します。

  • `SIGNING_KEY`: 先ほどコピーしたBase64文字列
  • `SIGNING_PASSWORD`: 秘密鍵に設定したパスフレーズ

ステップ3: GitHub Actions ワークフローの構築

`.github/workflows/release.yml` を以下のように作成します。

name: Secure Build and Sign

on:
push:
tags:

  • ‘v’ # vから始まるタグがプッシュされたときに発動

jobs:
build:
runs-on: ubuntu-latest

steps:

  • name: Checkout Code

uses: actions/checkout@v4

  • name: Set up JDK 17

uses: actions/setup-java@v4
with:
distribution: ‘temurin’
java-version: ’17’

# Base64で保存した秘密鍵を復元しつつ、Gradleに環境変数として渡す

  • name: Build and Sign with Gradle

env:
# GitHub SecretsからBase64文字列をデコードして環境変数にセット
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
run: |
# 必要であればここでデコード処理を挟む、あるいはGradle側で直接扱う
gradle publishToMavenLocal

※Mavenの場合は、GitHub Actions上で `GnuPG` アクションを使ってキーリングに鍵をインポートする手法をとります。

—

まとめ:あなたのコードの「身元証明」を自動化しよう

今回は、MavenとGradleを使ったビルド成果物のGPG署名と、CI/CD環境での安全な秘密鍵管理について解説しました。

  • Maven: `maven-gpg-plugin` を使って `verify` フェーズで自動署名。
  • Gradle: `signing` プラグインと `useInMemoryPgpKeys` を使って、セキュアかつスマートにインメモリ署名。
  • CI/CD: 秘密鍵は絶対にコードに含めず、Base64化してSecretsで安全に注入。

最初は「設定項目が多くて面倒くさいな」と感じるかもしれませんが、一度このパイプラインを組んでしまえば、あとはコードを書いてタグをプッシュするだけで、「世界に誇れる、改ざん不可能な信頼性の高いライブラリやプロダクト」が自動で組み上がっていきます。

こういう地味ながらも堅牢なエンジニアリングの積み重ねが、あなた自身の市場価値を確実に高めてくれます。ぜひ次のプロジェクトのビルド設定に取り入れてみてくださいね!

タイトルとURLをコピーしました