JKS 文件是一個 Java 中的密鑰管理庫。
JKS 文件就像一個倉庫,可以放很多的東西(密鑰)。
- 倉庫當然會有一把鎖(JKS 文件的密碼),防范別人隨便亂拿。
- 倉庫里面存放的密鑰也各有不同,每個密鑰都有一個名字(別名)。
- 密鑰對包含公鑰和私鑰。公鑰只要能進入倉庫就可以查看,私鑰則是有密碼的,只允許有權限的人查看。
Keytool 是一個 JAVA 環境下的安全鑰匙與證書的管理工具。
Keytool 將密鑰(key)和證書(certificates)存在一個稱為 keystore 的文件(受密碼保護)中。
在 keystore 里,包含兩種數據:
- 密鑰實體(Key entity)——密鑰(secretkey)又或者是私鑰和配對公鑰(采用非對稱加密)
- 可信任的證書實體(trustedcertificate entries)——只包含公鑰
生成 JKS 文件
keytool -genkeypair -alias jhxxb -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore jhxxb.jks -keypass keypass -storepass storepass -dname "CN=jhxxb.com, OU=jhxxb, O=jhxxb, L=wuhan, ST=hubei, C=CN" keytool -genkeypair -alias jhxxb -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore jhxxb.p12 -storetype PKCS12 -storepass storepass -dname "CN=jhxxb.com, OU=jhxxb, O=jhxxb, L=wuhan, ST=hubei, C=CN" keytool -genkey -alias jhxxb -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore jhxxb.jks -keypass keypass -storepass storepass -dname "CN=jhxxb.com, OU=jhxxb, O=jhxxb, L=wuhan, ST=hubei, C=CN" keytool -genkey -alias jhxxb -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keystore jhxxb.p12 -storetype PKCS12 -storepass storepass -dname "CN=jhxxb.com, OU=jhxxb, O=jhxxb, L=wuhan, ST=hubei, C=CN"
會在當前目錄下生成 jks 或 p12 文件。
CN=(名字與姓氏), OU=(組織單位名稱), O=(組織名稱), L=(城市或區域名稱),ST=(州或省份名稱), C=(國家名稱)
keytool -genkeypair -help 生成密鑰對 選項: -alias <alias> 要處理的條目的別名 -keyalg <keyalg> 密鑰算法名稱 -keysize <keysize> 密鑰位大小 -sigalg <sigalg> 簽名算法名稱 -destalias <destalias> 目標別名 -dname <dname> 唯一判別名 -startdate <startdate> 證書有效期開始日期/時間 -ext <value> X.509 擴展 -validity <valDays> 有效天數 -keypass <arg> 密鑰口令 -keystore <keystore> 密鑰庫名稱 -storepass <arg> 密鑰庫口令 -storetype <storetype> 密鑰庫類型 -providername <providername> 提供方名稱 -providerclass <providerclass> 提供方類名 -providerarg <arg> 提供方參數 -providerpath <pathlist> 提供方類路徑 -v 詳細輸出 -protected 通過受保護的機制的口令 使用 "keytool -help" 獲取所有可用命令
加載 JKS 文件
import lombok.Cleanup; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ClassPathResource; import org.springframework.util.StringUtils; import java.io.InputStream; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyStore; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAPublicKeySpec; @Slf4j public class RSAUtil { public static void main(String[] args) { // 從 classpath 下獲取 RSA 秘鑰對 KeyPair keyPair = loadKeyPairFromKeystore("jhxxb.jks", "storepass", "keypass", "jhxxb", "jks"); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 獲取 RSA 公鑰 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 獲取 RSA 私鑰 } public static KeyPair loadKeyPairFromKeystore(String keystoreFile, String storePassword, String keyPassword, String keyAlias, String type) { try { if (type == null) { String ext = StringUtils.getFilenameExtension(keystoreFile); type = ext == null ? KeyStore.getDefaultType() : ext; } KeyStore keyStore = KeyStore.getInstance(type); @Cleanup InputStream stream = new ClassPathResource(keystoreFile).getInputStream(); keyStore.load(stream, storePassword.toCharArray()); // PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyPassword.toCharArray()); RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyStore.getKey(keyAlias, keyPassword.toCharArray()); if (privateKey == null) { throw new RuntimeException("Couldn't load key with alias '" + keyAlias + "' from keystore"); } PublicKey publicKey; Certificate certificate = keyStore.getCertificate(keyAlias); if (certificate != null) { publicKey = certificate.getPublicKey(); } else { RSAPublicKeySpec spec = new RSAPublicKeySpec(privateKey.getModulus(), privateKey.getPublicExponent()); publicKey = KeyFactory.getInstance("RSA").generatePublic(spec); } return new KeyPair(publicKey, privateKey); } catch (Exception e) { throw new RuntimeException("Failed to load private key: " + e.getMessage(), e); } } }
https://my.oschina.net/lhplj/blog/1603887
https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator
https://www.hutool.cn/docs/#/crypto/非對稱加密-AsymmetricCrypto
https://gitee.com/jhxxb/MySpringCloud/tree/master/authorization-server/src/test/java/security
https://www.liaoxuefeng.com/wiki/1252599548343744/1304227968188450