PKCS12は、暗号化オブジェクトを単一ファイルとして保存するための標準化されたファイル形式です。この形式では、秘密鍵、公開鍵、証明書などを格納でき、JavaだけでなくC、C++、C#などの他の言語ライブラリとも互換性があります。PKCS12は主に他のキーストア形式との間でのデータ移行に利用されます。
PKCS12キーストアの作成
PKCS12形式のキーストアを利用するには、まずキーストアを初期化する必要があります。以下のコードで新規キーストアを作成できます:
try {
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(null, null);
store.store(new FileOutputStream("mykeystore.p12"), "mypass".toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
共通鍵の格納
PKCS12では共通鍵(Secret Key)も格納可能です。以下はAESアルゴリズムの鍵を生成して保存する例です:
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128);
SecretKey secret = generator.generateKey();
ks.setKeyEntry("aeskey", secret, "keypass".toCharArray(), null);
ks.store(new FileOutputStream("secrets.p12"), "storepass".toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
秘密鍵と証明書の格納
SSL/TLS通信などで利用される秘密鍵とその証明書チェーンをPKCS12に保存する方法は以下の通りです:
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);
CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA");
keypair.generate(1024);
PrivateKey privateKey = keypair.getPrivateKey();
X509Certificate cert = keypair.getSelfCertificate(
new X500Name("CN=localhost"), 365L * 24 * 3600);
X509Certificate[] certChain = {cert};
ks.setKeyEntry("mykey", privateKey, "keypass".toCharArray(), certChain);
ks.store(new FileOutputStream("identity.p12"), "storepass".toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
証明書のみの格納
秘密鍵なしで証明書単体を格納することも可能です:
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);
CertAndKeyGen gen = new CertAndKeyGen("RSA", "SHA1WithRSA");
gen.generate(1024);
X509Certificate cert = gen.getSelfCertificate(
new X500Name("CN=CA"), 365L * 24 * 3600);
ks.setCertificateEntry("rootca", cert);
ks.store(new FileOutputStream("truststore.p12"), "mypassword".toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
秘密鍵の読み込み
PKCS12から秘密鍵を取得する際は、適切なパスワードが必要です:
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream("identity.p12"), "storepass".toCharArray());
Key key = ks.getKey("mykey", "keypass".toCharArray());
System.out.println(key.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
証明書チェーンの取得
格納された証明書チェーンを取得するには以下のようにします:
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream("identity.p12"), "storepass".toCharArray());
Certificate[] chain = ks.getCertificateChain("mykey");
for (Certificate c : chain) {
System.out.println(c.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
単一証明書の取得
エイリアスに対応する証明書を取得する場合:
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream("truststore.p12"), "mypassword".toCharArray());
Certificate cert = ks.getCertificate("rootca");
System.out.println(cert.toString());
} catch (Exception e) {
e.printStackTrace();
}
他形式への移行
PKCS12からJKS形式へのデータ移行例:
try {
// PKCS12から読み込み
KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
pkcs12.load(new FileInputStream("source.p12"), "pkcs12pass".toCharArray());
Key key = pkcs12.getKey("importedkey", "keypass".toCharArray());
Certificate[] chain = pkcs12.getCertificateChain("importedkey");
// JKSに書き出し
KeyStore jks = KeyStore.getInstance("JKS");
jks.load(null, null);
jks.setKeyEntry("migrated", key, "newpass".toCharArray(), chain);
jks.store(new FileOutputStream("target.jks"), "jksstorepass".toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
PKCS12形式は、Java以外の環境とも連携可能な標準的なキーストア形式であり、特に相互運用性が求められるシナリオにおいて推奨されます。