java安装_Java中的证书透明度验证

java安装

java安装

因此,我有一个幼稚的想法,即除了证书有效性检查(在Java中)之外,将证书透明性验证作为每个请求的一部分也很容易。

牺牲了整个周末的一半时间,我可以证明这并不是一件小事。 但是,证书透明性是什么? 简而言之–它是世界上所有TLS证书的公开日志(即使SSL已过时,仍称为SSL证书)。 您可以检查该日志中是否发布了日志,如果没有发布,则有些可疑,因为CA必须将其所有已颁发的证书推送到日志中。 还有其他用例,例如为您的域注册新证书的通知,以检测可能被劫持的DNS管理面板或CA( Facebook免费提供了这样的工具)。

我想做的是前者–使来自Java应用程序的每个请求在证书透明性日志中验证对方的证书。 似乎这不是开箱即用的(如果可以,我找不到它。在一次有关JEP 244的讨论中,似乎讨论了与证书透明性相关的TLS扩展,但是我找不到它是否是最终支持)。

我开始认为您可以简单地获取证书,然后通过证书的指纹检查其是否包含在日志中。 这太容易了–允许通过哈希检查的日志,但是它不是证书的指纹,而是签名的证书时间戳-由日志在包含之前发布的签名。 引用CT RFC

SCT(签名证书时间戳)是日志将证书合并到Merkle树中的承诺

merkle树是一种非常酷的数据结构,它通过提供比整个日志短得多的“包含证明”,使外部参与者确信该日志中包含某些内容(从而节省了大量带宽)。 实际上,默克尔树的凉爽是为什么我首先对证书透明性感兴趣的原因(因为我们在我当前的面向日志的公司中使用默克尔树)

因此,为了检查是否包含,您必须以某种方式获取SCT。 最初,我认为使用Certificate Transparency Java库是可能的,但事实并非如此。 拥有它之后,您可以使用客户端在日志中对其进行检查,但是获取它比较困难。 (注意:对于服务器端验证,可以通过HTTP查询日志; 但是浏览器可以使用DNS查询来保留用户的匿名性)。

可以通过三种方式来获得SCT,具体取决于服务器和/或日志和/或CA选择支持的方式:SCT可以包含在证书中,也可以在TLS握手期间作为TLS扩展提供。 ,也可以在握手期间再次包含在TLS装订响应中。 不幸的是,我检查的少数证书中没有存储SCT,因此我必须进入较低级别并调试TLS握手。

我启用了TLS hadnshake冗长的输出,并且瞧瞧-那里什么都没有。 Google确实将SCT包含为TLS扩展(根据Qualys),但是Java输出没有说明任何内容。

幸运的是(?)Google发布了Conscrypt –一种基于Java的安全性提供程序,基于Google的OpenSSL分支。 事情开始变得一团糟……但我还是去了,包括Conscrypt并将其注册为安全提供程序。 我必须使用Conscrypt TrustManager(使用JDK中的所有受信任证书初始化)建立连接:

KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream(System.getenv("JAVA_HOME") + "/lib/security/cacerts"), "changeit".toCharArray());
ctx.init(null,new TrustManager[] {new TrustManagerImpl(trustStore, 
    null, null, null, logStore, null, 
    new StrictCTPolicy())}, new SecureRandom());
        

URL url = new URL("https://google.com");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ctx.getSocketFactory());
conn.connect();
conn.getInputStream();
conn.disconnect();

当然,它最初并不起作用,因为Conscrypt不提供某些核心接口(CTLogStore和CTPolicy类)的实现。 实际上,CTLogStore是保存有关所有已知日志的信息的重要位(我仍然觉得将“日志提供程序”简称为“ log”很奇怪,但这是公认的术语)。 有一个以JSON形式存在的已知日志列表,这很酷,只是花了我一段时间(在外部帮助下)才能弄清楚确切的公共密钥是什么。 它们是什么-RSA,ECC? 它们如何编码? 您在RFC和文档中都找不到。 在这里可以看到它是“ SubjectPublicKeyInfo ASN.1结构的DER编码”。 啊。

BouncyCastle进行营救。 我与BouncyCastle的恋爱关系深深。 我讨厌它的直观性和API的复杂性,但是我喜欢它(几乎)具有您可能需要的所有与密码相关的东西。 经过一段时间的尝试,试图弄清楚如何将公共密钥转换为PublicKey对象,我发现使用PublicKeyFactory.createKey(Base64.getDecoder().decode(base64Key)); 为您提供使用任何算法的参数-它可以返回椭圆曲线关键参数或RSA关键参数。 您只需要将它们包装在另一个类中,然后将它们传递到另一个工厂(典型的BouncyCastle),就可以拥有公共密钥。

当然,现在Google的Conscrypt不再起作用了,因为在转换之后,publicKey的编码版本与原始字节不相同,因此日志ID计算错误。 但是我经过一番思考后解决了这个问题,最后,它奏效了–查询了证书透明性日志,并证明该证书有效并且正确地包含在日志中。

整个代码可以在这里找到。 是的,它使用了几个安全提供程序,一些奇怪的BouncyCastle API和Google提供程序中缺少的一些简单实现。 可能会缓存已知的证书,以便不执行对日志的重复调用,但这超出了我的实验范围。

证书透明性似乎是当今互联网的核心内容。 但是,它是如此晦涩且难以使用。

为什么未列出列表中的公钥类型(它们至少应在公钥旁边放置一个OID,因为事实证明,并非所有日志都使用椭圆曲线-其中两个使用RSA)。 也许有一个很好的解释,但是为什么在日志中包括SCT而不是证书的指纹? 为什么不然后将SCT强制包含在证书中,而这又不需要对服务器和客户端进行额外配置,而又将其包含在需要升级的TLS握手中呢?

据我所知,由于数以百万计的让我们加密证书,因此证书透明性计划现在面临可伸缩性问题。 每个日志(提供者)都应将整个日志提供给所有请求它的人。 解决这不是一件容易的事,并且朝着这个方向进行了努力,但是目前尚无明显的解决方案。

最后,如果Java没有简便的方法来实现这一点,那么所有的加密库都可用,我想知道其他语言的情况如何。 他们支持证书透明性还是需要升级?

也许我们都很好,因为浏览器支持它,但是浏览器并不是发出HTTP请求的唯一对象。 API调用是一个巨大的用例,如果可以对其进行劫持,则所造成的损害甚至可能比被诱骗的单个用户还要大。 因此,我认为应该在两件事上付出更多的努力:1.改进RFC和2.改进编程生态系统。 我希望这篇文章至少能有所贡献。

翻译自: https://www.javacodegeeks.com/2019/01/certificate-transparency-verification-java.html

java安装

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值