通过java获取jks或keystore签名信息( jdk无法获取keystore的md5信息解决方案
- 介绍:
- Java KeyStore是一个用于存储密钥和证书的安全容器,它提供了保护密钥完整性的功能。在日常的开发和维护工作中,我们可能会需要获取证书的指纹信息,以验证证书的完整性或者进行其他相关的安全检查。然而,目前的Java开发工具箱(JDK)并没有提供直接的命令行工具来获取特定证书的MD5指纹。这种限制可能会给开发人员和系统管理员带来一些不便。
为了解决这个问题,我们创建了一个简单的Java程序,通过它,用户可以轻松地加载指定的KeyStore,遍历其中的所有证书,并获取每个证书的MD5、SHA-1和SHA-256指纹。这个程序不仅可以显示证书的指纹信息,还可以展示证书的其他重要信息,如公钥和证书详情。通过这个程序,用户可以在没有内置命令行工具支持的情况下,方便快捷地完成证书指纹的获取和验证工作。
在接下来的章节中,我们将详细介绍这个程序的代码结构、执行流程以及如何使用它来获取证书的指纹信息。
-
代码结构:
- 这个代码是一个名为
KeyStoreInfo
的Java类,包含了一个main
方法和一个辅助方法getFingerprint
。main
方法用于加载密钥库,遍历密钥库中的所有别名,并提取与显示相关信息。getFingerprint
方法用于计算证书的指纹。
- 这个代码是一个名为
-
代码执行流程:
- 代码首先检查是否提供了正确数量的参数,否则会显示使用说明并退出。
- 然后,它创建了一个
FileInputStream
对象来加载指定路径的密钥库文件。 - 使用
KeyStore.getInstance
和keystore.load
方法来加载密钥库。 - 使用
keystore.aliases
方法来获取密钥库中的所有别名,并遍历每一个别名。 - 对于每一个别名,它获取与之相关的证书和公钥,并显示它们。
- 使用
getFingerprint
方法来计算和显示证书的MD5、SHA-1和SHA-256指纹。 - 最终,关闭文件输入流。
-
计算指纹方法详解:
getFingerprint
方法接受一个证书对象和一个算法名称(如“MD5”、“SHA-1”或“SHA-256”)作为参数。- 使用
MessageDigest.getInstance
方法获取指定算法的MessageDigest
对象。 - 使用
certificate.getEncoded
和md.update
方法来准备数据。 - 使用
md.digest
方法来计算指纹。 - 最后,将字节数组转换为十六进制字符串并返回。
-
错误处理:
- 代码包含了基本的错误处理,如果在执行过程中发生异常,它会捕获异常并打印堆栈跟踪。
-
代码使用:
- 使用
javac
编译文件
javac -encoding UTF-8 KeyStoreInfo.java
- 运行编译后的
.class
文件提供两个参数keystore path
和password
java KeyStoreInfo your_app.keystore_path your_keystore_password
- 使用
-
全部代码:
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Enumeration;
public class KeyStoreInfo {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Usage: java KeyStoreInfo <keystore-path> <keystore-password>");
System.exit(1);
}
String keystorePath = args[0];
String keystorePassword = args[1];
try {
// 加载密钥库文件
FileInputStream is = new FileInputStream(keystorePath);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
// 提供密钥库密码
keystore.load(is, keystorePassword.toCharArray());
// 获取密钥库中的所有别名
Enumeration<String> enumeration = keystore.aliases();
while (enumeration.hasMoreElements()) {
String alias = enumeration.nextElement();
Certificate certificate = keystore.getCertificate(alias);
PublicKey publicKey = certificate.getPublicKey();
// 显示别名和公钥
System.out.println("Alias Name: " + alias);
System.out.println("Public Key: " + publicKey);
// 显示证书信息
System.out.println("Certificate: " + certificate.toString());
// 计算并显示 MD5, SHA-1, 和 SHA-256 指纹
System.out.println("MD5 Fingerprint: " + getFingerprint(certificate, "MD5"));
System.out.println("SHA-1 Fingerprint: " + getFingerprint(certificate, "SHA-1"));
System.out.println("SHA-256 Fingerprint: " + getFingerprint(certificate, "SHA-256"));
System.out.println("---");
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static String getFingerprint(Certificate certificate, String algorithm) {
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] publicKey = certificate.getEncoded();
md.update(publicKey);
byte[] digest = md.digest();
// 将字节转换为十六进制表示形式,并在每两个字符之间插入冒号
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
hexString.append(":"); // 添加冒号
}
// 移除最后一个冒号
hexString.deleteCharAt(hexString.length() - 1);
return hexString.toString().toUpperCase(); // 转换为大写
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}