博客
关于我
每天记录学习的新知识 :TLS/SSL证书验证
阅读量:495 次
发布时间:2019-03-07

本文共 4069 字,大约阅读时间需要 13 分钟。

自签名证书验证的实现与解释

本文将详细讲解如何实现自签名证书的验证过程,包括证书的获取与加载以及证书的有效性校验等相关步骤。

第一部分:加载本地证书,创建SSLContext

在实现SSLSocketFactory之前,我们需要先完成以下步骤:

  • 获取本地证书流

    首先,通过AppManager.getContext().getAssets().open("root.cer")获取本地证书流InputStream,该证书文件通常以.cer格式存储。

  • 获取CertificateFactory

    使用CertificateFactory.getInstance("X509")获取证书工厂实例,该工厂用于生成X.509格式的证书对象。

  • 创建KeyStore

    使用KeyStore.getInstance(KeyStore.getDefaultType())初始化密钥仓库KeyStore,默认的密钥仓库类型通常为KeyStore.getDefaultType()

  • 加载KeyStore

    调用keyStore.load(null)加载密钥仓库信息,null表示无需指定初始参数。

  • 设置证书

    通过keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate))将载到的证书分配给指定的别名Integer certificateAlias = Integer.toString(1)。需要注意的是,certificate流在此过程中应妥善关闭,以避免资源泄漏。

  • 创建TrustManagerFactory

    使用TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())获取信任管理器工厂实例。该工厂的初始方法init(keyStore)将密钥仓库中的可信证书供应给信任管理器。

  • ** 初始化SSLContext**

    调用SSLContext.getInstance("TLS")获取SSL/TLS协议的安全套接字上下文实例。然后通过sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom())初始化SSLContext,指定自定义的信任管理器x509TrustManager

  • ** 获取SSLSocketFactory**

    最终,通过sslContext.getSocketFactory()获取SSLSocketFactory实例,该实例将用于创建安全套接字。

  • 第二部分:证书的校验

    在完成SSL/TLS连接后,证书的有效性校验至关重要。以下将详细描述如何实现自签名证书的校验过程。

  • 验证客户端证书(若需要,按需使用)

    在实际应用中,如果需要验证客户端的证书,可以实现checkClientTrusted方法。该方法会检查客户端提供的证书是否可信,通常在默认情况下,信任所有证书。

  • 验证服务器证书

    实现checkServerTrusted方法,用于检查服务器端的证书是否有效。在实际实现中,我们通常需要确保以下几点:

    • 调用cert.checkValidity()检查证书是否已过期或不再有效。
    • 使用服务器证书的公钥通过cert.verify(publicKey)对证书的签名进行验证,以确保证书是由可信的证书颁发机构签发的。
    • 处理可能出现的异常情况,如InvalidKeyExceptionNoSuchAlgorithmException等,并根据需要抛出定制的异常。
  • 证书的有效性判断

    在完成上述验证后,可以通过检查证书的有效期和签名是否正确来判断证书的状态。如出现异常,应及时处理并抛出明确的异常信息。

  • 服务器端证书的获取

    服务器端证书的获取通常采用文件流方式,如:

    InputStream inputStream = new BufferedInputStream(AppManager.getContext().getAssets().open("root.cer"));CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");serverCert = (X509Certificate) certificateFactory.generateCertificate(inputStream);

    需要注意的是,在实际应用中,应妥善关闭输入流以释放资源。

  • X509TrustManager的实现

    在实际代码中,我们通常需要自定义信任管理器类X509TrustManager,以实现对证书的高度定制化验证。其实现方式如下:

    private X509TrustManager x509TrustManager = new X509TrustManager() {    @Override    public void checkClientTrusted(X509Certificate[] chain, String authType) {        LogUtils.i(TAG, "checkClientTrusted");    }    @Override    public void checkServerTrusted(X509Certificate[] chain, String authType) {        LogUtils.i(TAG, "checkServerTrusted");        if (chain == null || chain.length < 1) {            throw new IllegalArgumentException("check server X509Certificate is null or empty");        }        LogUtils.i(TAG, "chain length: " + chain.length);        int errorCount = 0;        for (X509Certificate cert : chain) {            try {                cert.checkValidity();                PublicKey publicKey = getServerCert().getPublicKey();                cert.verify(publicKey);            } catch (InvalidKeyException e) {                LogUtils.e(TAG, "InvalidKeyException: " + e.getMessage());                e.printStackTrace();                errorCount++;            } catch (NoSuchAlgorithmException e) {                LogUtils.e(TAG, "NoSuchAlgorithmException: " + e.getMessage());                e.printStackTrace();                errorCount++;            } catch (NoSuchProviderException e) {                LogUtils.e(TAG, "NoSuchProviderException: " + e.getMessage());                e.printStackTrace();                errorCount++;            } catch (SignatureException e) {                LogUtils.e(TAG, "SignatureException: " + e.getMessage());                e.printStackTrace();                errorCount++;            }        }        if (errorCount == chain.length) {            LogUtils.i(TAG, "证书验证失败!");            throw new CertificateException(new SignatureException());        } else {            LogUtils.i(TAG, "证书验证成功!");        }    }    @Override    public X509Certificate[] getAcceptedIssuers() {        LogUtils.i(TAG, "getAcceptedIssuers");        return new X509Certificate[0];    }};

    总结

    通过以上步骤,我们可以实现自签名证书的验证过程。一方面,通过加载本地证书,并基于 SSL/TLS协议创建安全套接字,以及另一方面,通过定制化信任管理器对服务器证书的有效性进行验证,确保通信过程中的安全性。

    转载地址:http://ztvcz.baihongyu.com/

    你可能感兴趣的文章
    OSPF技术连载11:OSPF 8种 LSA 类型,6000字总结!
    查看>>
    OSPF技术连载12:OSPF LSA泛洪——维护网络拓扑的关键
    查看>>
    OSPF技术连载13:OSPF Hello 间隔和 Dead 间隔
    查看>>
    OSPF技术连载14:OSPF路由器唯一标识符——Router ID
    查看>>
    OSPF技术连载15:OSPF 数据包的类型、格式和邻居发现的过程
    查看>>
    OSPF技术连载16:DR和BDR选举机制,一篇文章搞定!
    查看>>
    OSPF技术连载17:优化OSPF网络性能利器——被动接口!
    查看>>
    OSPF技术连载18:OSPF网络类型:非广播、广播、点对多点、点对多点非广播、点对点
    查看>>
    OSPF技术连载19:深入解析OSPF特殊区域
    查看>>
    SQL Server 复制 订阅与发布
    查看>>
    OSPF技术连载20:OSPF 十大LSA类型,太详细了!
    查看>>
    OSPF技术连载21:OSPF虚链路,现代网络逻辑连接的利器!
    查看>>
    OSPF技术连载22:OSPF 路径选择 O > O IA > N1 > E1 > N2 > E2
    查看>>
    OSPF技术连载2:OSPF工作原理、建立邻接关系、路由计算
    查看>>
    OSPF技术连载5:OSPF 基本配置,含思科、华为、Junifer三厂商配置
    查看>>
    OSPF技术连载6:OSPF 多区域,近7000字,非常详细!
    查看>>
    OSPF技术连载7:什么是OSPF带宽?OSPF带宽参考值多少?
    查看>>
    OSPF技术连载8:OSPF认证:明文认证、MD5认证和SHA-HMAC验证
    查看>>
    OSPF故障排除技巧
    查看>>
    spring配置文件中<context:property-placeholder />的使用
    查看>>