验证 RSA 密钥是否与 Java 中的 X.509 证书匹配

2024-03-01

我有一个 RSA 密钥和一个用于 SSL 连接的 X.509 证书。

密钥和证书存储在 PEM 格式的文件中(由 OpenSSL 生成)并在 Apache HTTP 服务器环境中使用。

有没有一种简单的方法可以仅使用 Java 代码(不执行 openssl 二进制文件并解析输出)来验证密钥是否与证书匹配,例如使用 Java 安全性和/或 Bouncycastle 库方法?


以下代码比较公钥和私钥中的 SHA-1 模数。每对的模数应该是唯一的(当然,除非您的密钥对生成机制或随机生成器被破坏)。

请注意,以下代码要求密钥采用未加密的 PKCS#8 格式。最好使用 PKCS#12 并将二进制 PKCS#12 文件加载到 KeyStore 中(提供密码)。

openssl pkcs8 -topk8 -in key.pem -out keypk8.pem -nocrypt

最后是Java代码:

import static org.bouncycastle.util.encoders.Hex.toHexString;

import java.io.ByteArrayInputStream;
import java.io.FileReader;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;

import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

public class CompareCertAndKey {

    /**
     * Checks if the certificate and RSA private key match.
     * 
     * @param args the path to the certificate file in args[0] and that of the private key in args[1]
     */
    public static void main(String[] args) {
        try {
            final PemReader certReader = new PemReader(new FileReader(args[0]));
            final PemObject certAsPemObject = certReader.readPemObject();
            if (!certAsPemObject.getType().equalsIgnoreCase("CERTIFICATE")) {
                throw new IllegalArgumentException("Certificate file does not contain a certificate but a " + certAsPemObject.getType());
            }
            final byte[] x509Data = certAsPemObject.getContent();
            final CertificateFactory fact = CertificateFactory.getInstance("X509");
            final Certificate cert = fact.generateCertificate(new ByteArrayInputStream(x509Data));
            if (!(cert instanceof X509Certificate)) {
                throw new IllegalArgumentException("Certificate file does not contain an X509 certificate");
            }

            final PublicKey publicKey = cert.getPublicKey();
            if (!(publicKey instanceof RSAPublicKey)) {
                throw new IllegalArgumentException("Certificate file does not contain an RSA public key but a " + publicKey.getClass().getName());
            }

            final RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
            final byte[] certModulusData = rsaPublicKey.getModulus().toByteArray();

            final MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
            final byte[] certID = sha1.digest(certModulusData);
            final String certIDinHex = toHexString(certID);


            final PemReader keyReader = new PemReader(new FileReader(args[1]));
            final PemObject keyAsPemObject = keyReader.readPemObject();
            if (!keyAsPemObject.getType().equalsIgnoreCase("PRIVATE KEY")) {
                throw new IllegalArgumentException("Key file does not contain a private key but a " + keyAsPemObject.getType());
            }

            final byte[] privateKeyData = keyAsPemObject.getContent();
            final KeyFactory keyFact = KeyFactory.getInstance("RSA");
            final KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyData);
            final PrivateKey privateKey = keyFact.generatePrivate(keySpec);
            if (!(privateKey instanceof RSAPrivateKey)) {
                throw new IllegalArgumentException("Key file does not contain an X509 encoded private key");
            }
            final RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
            final byte[] keyModulusData = rsaPrivateKey.getModulus().toByteArray();
            final byte[] keyID = sha1.digest(keyModulusData);
            final String keyIDinHex = toHexString(keyID);

            System.out.println(args[0] + " : " + certIDinHex);
            System.out.println(args[1] + " : " + keyIDinHex);
            if (certIDinHex.equalsIgnoreCase(keyIDinHex)) {
                System.out.println("Match");
                System.exit(0);
            } else {
                System.out.println("No match");
                System.exit(-1);
            }
        } catch (Exception e) {
            e.printStackTrace(System.err);
            System.exit(-2);
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

验证 RSA 密钥是否与 Java 中的 X.509 证书匹配 的相关文章

随机推荐

  • Windows 或 ASP.NET 服务中的 System.Drawing

    根据MSDN http msdn microsoft com en us library system drawing aspx 在 中使用类并不是一个特别好的主意系统图Windows 服务或 ASP NET 服务中的命名空间 现在我正在开
  • 将证书从智能卡复制到计算机

    是否可以将证书从智能卡复制到计算机并 用它来登录某个站点 在 Mac 上 这些证书出现在钥匙串中 并且可以保存到磁盘 但我不确定如何强制站点提示对话框屏幕以选择证书 连接智能卡后 会出现提示并要求选择证书 智能卡包含由封装在 X509 证书
  • 隐藏重复行 SSRS 2008 R2

    我的报告中出现重复的数据 因为源表有重复的数据 在不创建组的情况下 我想隐藏重复的数据写入表达式 所以我做了什么 我选择表行并为表行的隐藏属性添加一个表达式 表情就像是 上一个 字段 ID 值 字段 ID 值 但它不起作用 仍然显示重复的数
  • 选择组中第 i 个 jQuery 对象比 $($(".someclass")[i])) 更简单的方法?

    所以我试图循环遍历 someclass 的成员 不是 DOM 元素 而是它们的 jQuery 对应元素 我一直在使用 someclass i 但这非常丑陋 有更自然的方法来做到这一点吗 你可以使用eq http api jquery com
  • 动态控件组和复选框无样式

    所以我尝试将动态内容直接加载到我的复选框容器 group checkboxes 中 div div 这是我正在运行的用于填充容器的语句 group checkboxes append fieldset fieldset
  • 使重叠内容的容器适合最大孩子的高度

    我正在构建一个在 3 个引号之间旋转的轮播 幻灯片类型小部件 假设标记如下所示 div class carousel blockquote blockquote blockquote blockquote blockquote blockq
  • Laravel 中的“请提供有效的缓存路径”错误

    我复制了一个正在运行的 Laravel 应用程序并将其重命名以用于另一个应用程序 我删除了供应商文件夹并再次运行以下命令 composer self update composer update npm install bower inst
  • 表格页脚自动跨过表格宽度

    我有一张桌子 里面有动态列数取决于我收到的数据 我有一个标签需要分布在所有列上 与表中的列数无关 table thead tr th span ColA span th th span ColB span th th span Col br
  • 为什么gcc中malloc将值初始化为0?

    可能各个平台的情况不一样 但是 当我使用 gcc 编译并运行下面的代码时 我在 ubuntu 11 10 中每次都得到 0 include
  • Microsoft.FSharp.Math.Matrix 发生了什么?

    有点奇怪 这个类类型如何从 VS2010 发布的 F 中删除 有谁知道它去哪儿了 或者现在在哪里 它位于 F powerpack 中 F 团队将其用于 不稳定 代码 这些代码的发布和更新频率将高于 F 和库的主要版本 请注意 该代码仍然是高
  • 与scala反射库不一致

    我无法理解为什么在 2 11 1 中使用 scala 的运行时反射会给出看似不一致的结果 我正在尝试检查 java 对象中包含的字段的类型 如下所示 import java util List import java util ArrayL
  • 如何在jquery中缓慢改变背景属性?

    我想要为背景设置动画 但它不会随 animate 改变 document ready function menu hover function this stop animate background moz radial gradient
  • 如何防止在 Cloudflare 上暴露源 IP 地址?

    在 Cloudflare DNS 设置页面上 它指出An A AAAA CNAME or MX record is pointed to your origin server exposing your origin IP address
  • 列表框数据模板 - 只能通过单击子元素来选择项目,而不仅仅是项目上的任何位置

    我有一个带有项目数据模板的列表框 问题在于 仅通过单击项目上的任意位置无法选择项目 必须选择项目 我必须单击特定的子元素才能使其实际工作 我的项目有一个图像和一个文本块 如果我将鼠标悬停在图像或文本块上 我实际上会看到悬停效果 如果我将鼠标
  • Spring-boot Resttemplate response.body 为 null 而拦截器清楚地显示 body

    使用 Spring boot 1 5 10 RELEASE 我得到的 response body 为 null 这是我使用 RestTemplate 的方式 RestTemplate restTemplate new RestTemplat
  • Maven javadoc + 自定义 doclet

    从命令行调用 mvn 时如何指定 dolect 工件 mvn clean install javadoc javadoc Ddoclet my Doclet DdocletArtifact 你应该添加这样的东西到你的pom xml
  • 具有动态谓词的表的最佳索引

    我想优化SQL Server中下表的查询速度 CREATE TABLE dbo PriceNodeLookupIndex Id int IDENTITY 1 1 NOT NULL PriceNodeId int NOT NULL ItemI
  • 如何解决 TypeError: 无法序列化 float Python Elementtree

    我有一个调试问题 由于我是新来的 请原谅可能的简陋文字墙 经过几个小时我终于得到了elementtree做我想做的事 但我无法输出我的结果 因为 tree write output3 xml 也 print ET tostring root
  • 如何使用 Python 和 web3.py 调用智能合约函数

    我在以太坊测试网络上部署了一个合约 其中包含一些功能 并且它们在使用 Remix 界面时都恰好可以工作 当尝试在 Python 中使用 web3 py 调用这些函数时 我只能调用公共函数 并且该部分工作正常 问题是调用具有 限制 的函数 例
  • 验证 RSA 密钥是否与 Java 中的 X.509 证书匹配

    我有一个 RSA 密钥和一个用于 SSL 连接的 X 509 证书 密钥和证书存储在 PEM 格式的文件中 由 OpenSSL 生成 并在 Apache HTTP 服务器环境中使用 有没有一种简单的方法可以仅使用 Java 代码 不执行 o