Java MTLS 主题和发行人订单

Java MTLS Subject and Issuer order

我们正在升级我们与合作伙伴之间的连接,他们要求我们升级到 MTLS。我一直在调试低级别 java、

javax.net.debug=all 我可以看到握手成功。然而,合作伙伴对 Subject 和 Issuer 字段进行了完整的字符串匹配,并与他们数据库中的某些字段进行了比较。

我使用了以下内容,

   if (cert instanceof X509Certificate) {
        X509Certificate x509cert = (X509Certificate) cert;

        // Get subject
        Principal principal = x509cert.getSubjectDN();
        String subjectDn = principal.getName();
        logger.error(subjectDn);
        // Get issuer
        principal = x509cert.getIssuerDN();
        String issuerDn = principal.getName();
        logger.error(issuerDn);
    }

转储 java 的值。一个有趣的注释 openssl 以与 java 报告完全不同的顺序报告它们。

我现在一直在 Wireshark 中挖掘,我可以从那个级别看到握手,但是,它似乎尽可能将名称翻译成 id-at-commonNamepkcs-9-at-emailAddress .

有什么方法可以知道实际发送的是什么?

没有协议 MTLS,但听起来您关心的是 TLS 中的客户端身份验证,也称为相互身份验证,它与服务器身份验证一样通常使用 X.509 类型(更准确地说,PKIX)证书。

背景:X.509/PKIX 证书使用 X.500/501 Distinguished Name structure 也称为 X500Name、X501Name 或简称为名称来标识主题和颁发者(有时在某些扩展中是其他 things/entities)。这种结构在 ASN.1 中定义为 RelativeDistinguishedName 项的序列(有序),每个项都是正式的一组(无序)属性类型和值对(序列),尽管实际上 RDN 集合几乎总是单例,所以名称实际上是属性类型和值的序列。此名称格式旨在用于 'directories' 的全球分布式分层网络,而不是像 DNS 除了(因为 CCITT-now-ITU-T 是一个组织政府机构)主要植根于基于国家/地区的国家目录,而不是功能性目录或 'generic' 类似 .com .org .edu .gov .mil .net 的目录,并且 X.509 证书基本上被设计为从可脱机使用的目录网络导出数据。实际上,真正的 X.500 目录根本不被使用,甚至像 LDAP(轻量级目录访问协议)这样的协议也很少使用,除了 Microsoft Windows 'domains'(Active Directory) ,但 X.509 证书(包括其中使用的名称格式)广泛用于 SSL-now-TLS、S/MIME 和许多其他应用程序。

DN 的常规文本或外部形式是一系列 attr=value 项,其中 attr 通常缩写,例如C 代表国家,ST 代表州或省,CN 代表 CommonName,等等。Java 使用 RFC 1485、1779、2253 和 4514 定义的标准化格式(小 changes/improvements),其中各项用逗号和以相反顺序给出,即从最后(最低级别)到第一个(最高级别通常是根),类似于 DNS。例如 Java 将 www.duckduckgo.com 当前使用的证书的主题显示为

CN=*.duckduckgo.com, O="Duck Duck Go, Inc.", L=Paoli, ST=Pennsylvania, C=US

OpenSSL 传统上默认使用一种格式,每个项目前面有斜杠 (而不是逗号 分隔 它们),并且还进入 转发订单

/C=US/ST=Pennsylvania/L=Paoli/O=Duck Duck Go, Inc./CN=*.duckduckgo.com

但 1.1.0 向上更改了默认使用逗号分隔符的前向顺序

C = US, ST = Pennsylvania, L = Paoli, O = "Duck Duck Go, Inc.", CN = *.duckduckgo.com 

一些OpenSSL命令行操作,如x509,支持其他显示格式;请参阅“名称选项”下的手册页。特别是 x509 -nameopt oneline,dn_rev 给出的格式几乎与 Java:

相同
CN = *.duckduckgo.com, O = "Duck Duck Go, Inc.", L = Paoli, ST = Pennsylvania, C = US

Wireshark 如果您只查看已传输证书(在 TLS 中)的 摘要 ,则以相反的顺序显示带有全名而不是属性缩写的 attribute=value 对像 RFC 和 Java:

但是如果您单击加号框展开几个级别,您可以分别看到每个属性项的结构,按正向顺序排列:

正是因为显示格式存在并且一直存在多种变化,所以将 DN 作为字符串进行比较并不是一个好主意。如果您需要将其作为字符串存储在例如一个数据库,更好的方法是从字符串重建结构化形式——使用一致的顺序、缩写等约定——并比较结构化对象。如果您阅读 javadoc 并看到 X509Certificate.getIssuerDN() and similarly .getSubjectDN() are 'denigrated' (apparently intended to be 'deprecated') and superseded since Java 1.4 by .getIssuerX500Principal() and .getSubjectX500Principal() which use a documented API class (instead of an opaque internal class) javax.security.auth.x500.X500Principal 和记录的 .equals() 操作,这会变得更容易一些。