HTTPS 发送请求出现TLS握手失败2

news2024/10/2 1:39:42

之前写过一篇《HTTPS 发送请求出现TLS握手失败》,后续来了;

之前发现https进行握手缺少椭圆曲线,是因为手动删除provider导致的:

    static {
        Security.removeProvider("SunEC");
    }

深入分析之后发现,虽然这里把椭圆曲线删除了,但是其实别的工具类会把

BouncyCastleProvider给加上,代码如下:
    static {
        Security.removeProvider("BC");
        Security.addProvider(new BouncyCastleProvider());
    }

这是一个叫CommonUtil的工具类,在工具类被加载的时候会执行static里面的代码;分析后发现,在请求进来之后,切面会拦截请求,切面里面有个参数校验的方法会调用CommonUtil里面的方法,因此这段静态代码是会被执行的,加断点调试,确实是可以执行的;

通义千问对这个BouncyCastle的解释如下:

Bouncy Castle 是一个用 Java 和 C# 编写的加密库,它提供了广泛的算法实现和协议支持。对于 Java 开发者来说,Bouncy Castle 提供了一个名为 `bcprov-jdk15on`(或针对不同 JDK 版本的其他变体)的 Java 密码工具包,可以用来增强标准 Java 安全性框架的功能。

在 Bouncy Castle 中,你可以找到许多标准和非标准的加密算法,包括但不限于:

- 对称加密算法,如 AES, DES, 3DES, Blowfish 等。
- 非对称加密算法,如 RSA, DSA, ECDSA, ElGamal 等。
- 消息摘要算法,如 SHA-1, SHA-256, SHA-512, MD5 等。
- 密钥协商和密钥交换协议,如 DH (Diffie-Hellman) 和 ECDH (Elliptic Curve Diffie-Hellman)。
- 数字签名算法,如 PSS (Probabilistic Signature Scheme) 和 PKCS#1 v1.5。
- 随机数生成器和安全随机数生成器。
- 加密模式,如 CBC (Cipher Block Chaining),CFB (Cipher Feedback),CTR (Counter Mode) 等。
- MACs (Message Authentication Codes),如 CMAC, HMAC 等。

要使用 Bouncy Castle 的 Java 密码包,你需要将其添加到你的项目依赖中。如果你使用 Maven 或 Gradle 构建系统,可以在你的 `pom.xml` 或 `build.gradle` 文件中添加相应的依赖项。例如,在 Maven 中,你可能需要添加以下依赖:

```xml
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>版本号</version>
</dependency>
```

将 `版本号` 替换为最新或所需的 Bouncy Castle 版本。

一旦你添加了依赖项,你就可以在你的代码中使用 Bouncy Castle 提供的类和方法来执行各种加密操作。例如,创建一个 RSA 密钥对、加密数据或验证数字签名等。务必确保你的应用程序正确地初始化了 Bouncy Castle 安全提供程序,以便使用其功能。这通常通过调用 `Security.addProvider(new BouncyCastleProvider());` 来完成。

由此可见,这个包是包含常用的一些加密方法的,同时也包含国密的加密套件,问过写这个代码的同事,他说当时是因为有些项目需要使用国密的签名方法,所以使用这个包的Provider替换了原有的SunEC Provider,避免了名称的冲突;

问题就来了,既然已经加入了可以替换原有的加密套件的新的更强大的套件,那为啥还没握手失败呢?

后面加断点调试,以及分析SSL Handshake报文,发现,在执行外部接口的post请求之前,会有一次handshake的过程, 报文如下:

"ClientHello": {
  "client version"      : "TLSv1.2",
  "random"              : "06 A8 9E AD 6D 16 42 E1 69 0B F7 A7 24 00 F0 BE 29 CC 12 1D 2C DA 3A 5C A8 EE FA 13 BB 05 F6 CF",
  "session id"          : "3A 6B 87 F9 FC 27 80 F8 EE B5 9A AB 5F C7 23 16 B8 D1 56 CB F0 DB 59 4C 47 F0 F0 A7 78 B4 6C FF",
  "cipher suites"       : "[TLS_AES_256_GCM_SHA384(0x1302), TLS_AES_128_GCM_SHA256(0x1301), TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(0xC02B), TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F), TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(0x00A3), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(0xC024), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(0xC028), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(0xC023), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(0xC027), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(0x0067), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040), TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(0xC02E), TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(0xC032), TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(0xC02D), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(0xC031), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(0xC026), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(0xC02A), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(0xC025), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(0xC029), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(0xC00A), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(0xC014), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(0xC009), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(0xC013), TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039), TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033), TLS_DHE_DSS_WITH_AES_128_CBC_SHA(0x0032), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(0xC005), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(0xC00F), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(0xC004), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(0xC00E), TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D), TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C), TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D), TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C), TLS_RSA_WITH_AES_256_CBC_SHA(0x0035), TLS_RSA_WITH_AES_128_CBC_SHA(0x002F)]",
  "compression methods" : "00",
  "extensions"          : [
    "supported_groups (10)": {
      "versions": [secp256r1, secp384r1, secp521r1, ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144, ffdhe8192]
    },
    "ec_point_formats (11)": {
      "formats": [uncompressed]
    },
    "signature_algorithms (13)": {
      "signature schemes": [ed25519, ed448, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384, ecdsa_secp521r1_sha512, rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, dsa_sha256, ecdsa_sha1, rsa_pkcs1_sha1, dsa_sha1]
    },
    "signature_algorithms_cert (50)": {
      "signature schemes": [ed25519, ed448, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384, ecdsa_secp521r1_sha512, rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, dsa_sha256, ecdsa_sha1, rsa_pkcs1_sha1, dsa_sha1]
    },
    "extended_master_secret (23)": {
      <empty>
    },
    "supported_versions (43)": {
      "versions": [TLSv1.3, TLSv1.2]
    },
    "psk_key_exchange_modes (45)": {
      "ke_modes": [psk_dhe_ke]
    },
    "key_share (51)": {
      "client_shares": [  
        {
          "named group": secp256r1
          "key_exchange": {
            0000: 04 D6 83 24 55 B1 EC F4   50 9D E6 FD 57 14 EC 68  ...$U...P...W..h
            0010: 5D 7C 40 C8 4F B0 47 9D   3C B9 0F 5C 49 48 52 CF  ].@.O.G.<..\IHR.
            0020: 81 ED 8B FF 57 BF CD 6D   E9 05 61 0C 95 DD 62 66  ....W..m..a...bf
            0030: 78 9D 8E E5 7A 28 8F B9   FA A3 C3 90 EC B8 7F 65  x...z(.........e
            0040: 14 
          }
        },
      ]
    },
    "renegotiation_info (65,281)": {
      "renegotiated connection": [<no renegotiated connection>]
    }
  ]
}
)
javax.net.ssl|FINE|01 04|Druid-ConnectionPool-Create-491712|2024-07-09 10:30:10.007 CST|ServerHello.java:863|Consuming ServerHello handshake message (
"ServerHello": {
  "server version"      : "TLSv1.2",
  "random"              : "BF BB 99 F7 7A 01 93 1D 44 7D 09 E6 9B 2E 61 E9 C1 2C F0 7B 74 D2 A9 E5 1E 3B 35 61 47 BD D1 4A",
  "session id"          : "36 9D 0D 19 32 B6 2B AC 3B E7 55 12 B9 50 82 36 F8 A8 3B C7 13 73 71 C5 FD 0C 8F 51 A8 1C 2A 2C",
  "cipher suite"        : "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030)",
  "compression methods" : "00",
  "extensions"          : [
    "renegotiation_info (65,281)": {
      "renegotiated connection": [<no renegotiated connection>]
    },
    "ec_point_formats (11)": {
      "formats": [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
    },
    "extended_master_secret (23)": {
      <empty>
    }
  ]
}
)

为什么会这样呢?同事的解释是这样的:

那次handshake就已经让sslcontext完成了初始化,而为什么随着spring bean生命周期的可以,是因为在接受任何请求前,也就是没有将sslcontext初始化,所以加了provider能够生效,因为之前有bean已经删了sunEC的provider这时已经没有支持快签接口的套件了,由于commonutil初始化前已经进行了handshake并完成了sslcontext的初始化

先看一下sslcontext的源码:

public class SSLContext {
    private final Provider provider;

    private final SSLContextSpi contextSpi;

    private final String protocol;

    /**
     * Creates an SSLContext object.
     *
     * @param contextSpi the delegate
     * @param provider the provider
     * @param protocol the protocol
     */
    protected SSLContext(SSLContextSpi contextSpi, Provider provider,
            String protocol) {
        this.contextSpi = contextSpi;
        this.provider = provider;
        this.protocol = protocol;
    }

    private static SSLContext defaultContext;

 也就是说sslcontext类里面有个静态的SSLContext:

private static SSLContext defaultContext;

SSLContext sslcontext =ssLcontext.getDefault();

 httpclient密码套件通过这个获取的:

这个里面会初始化provider,也就是说,第一个handshake请求触发的时候,就会触发getInstance方法,从而实例化provider,这样在handshake完成之后再执行下面的语句是没有用的:

    static {
        Security.removeProvider("BC");
        Security.addProvider(new BouncyCastleProvider());
    }

 已经实例化了的provider是没有更新的,它不会把新的provider加到已经实例化的静态的instance下的provider成员变量里面;除非调用httpclient那段代码使用新的sslconext;

所以,正确的解决方式是,在被spring容器管理的某个bean中执行:

Security.addProvider(new BouncyCastleProvider());这样在需要使用加密套件的地方就会有provider;

所以,我这里正确的解决方式是,在之前只是删了provider的类的静态代码块里加语句:

原代码:

static {
        Security.removeProvider("SunEC");
    }

修改后的代码:

static {
        Security.removeProvider("SunEC");
        Security.addProvider(new BouncyCastleProvider());
    }

这样可以解决问题,同时也不会对原有的代码造成影响!到这里,这个问题暂告一段落了,但是实际上这个问题还没有彻底解决;为啥子呢?因为对方服务的运维说他们的服务器最近没有修改过,TLSv1.2以上的版本要求是从2年前就这样的了,而我们这边的代码最近也没有改动到这一块,那这个问题到底是因为什么而触发的,不得而知,是个谜!同事分析说可能是对方服务器最近更新了密码套件之类引起的,因为以前也出现过这样的情况,但是我没遇到过,我只能问一下他们确认一下了, 但是他们说没改动过的,这就无解了,没办法,暂时先这样吧,问题是解决了,就是不知道引发问题的原因。

解释得有点乱:(

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1912795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工控巨头360亿疯狂收购全球子业务,真的成为巨无霸了!

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 工业自动化领域的领航者霍尼韦尔&#xff0c;近期宣布了一项震撼业界的交易——成功完成对开利公司全球安防业务的收购&#xff0c;交易额高达49…

使用ResizeObserver观察DOM元素的尺寸变化

文章目录 关于ResizeObserver示例代码示例代码结果如下所示echarts自适应容器div大小示例代码结果如下所示echarts自适应容器大小的方式二 关于ResizeObserver 关于这个Web API&#xff0c;可以看mdn的官网&#xff0c;ResizeObserver - Web API | MDN (mozilla.org)&#xff…

图论---匈牙利算法求二分图最大匹配的实现

开始编程前分析设计思路和程序的整体的框架&#xff0c;以及作为数学问题的性质&#xff1a; 程序流程图&#xff1a; 数学原理&#xff1a; 求解二分图最大匹配问题的算法&#xff0c;寻找一个边的子集&#xff0c;使得每个左部点都与右部点相连&#xff0c;并且没有两条边共享…

AI提示词:打造爆款标题生成器

打开GPT输入以下内容&#xff1a; # Role 爆款标题生成器## Profile - author: 姜小尘 - version: 02 - LLM: Kimi - language: 中文 - description: 利用心理学和市场趋势&#xff0c;生成吸引眼球的自媒体文章标题。## Background 一个吸引人的标题是提升文章点击率和传播力…

(四)前端javascript中的数据结构之归并排序

归并排序是一种分治算法&#xff0c; 其思想是&#xff1a; 将原始数组切分成较小的数组&#xff0c;直到每个小数组只有一 个位置&#xff0c;接着将小数组归并成较大的数组&#xff0c;直到最后只有一个排序完毕的大数组 归并排序是第一个可以被实际使用的排序算法。它比前面…

中职网络安全wire0077数据包分析

从靶机服务器的FTP上下载wire0077.pcap&#xff0c;分析该文件&#xff0c;找出黑客入侵使用的协议&#xff0c;提交协议名称 SMTP 分析该文件&#xff0c;找出黑客入侵获取的zip压缩包&#xff0c;提交压缩包文件名 DESKTOP-M1JC4XX_2020_09_24_22_43_12.zip 分析该文件&…

JavaScript中的执行上下文和原型链

目录 一、执行上下文 1.执行上下文 2.执行上下文栈 3.闭包 1&#xff09;定义 2&#xff09;形成条件 3&#xff09;例子 &#xff08;1&#xff09;例子1&#xff1a;简单闭包 &#xff08;2&#xff09;例子2&#xff1a;闭包与循环 &#xff08;3&#xff09;例子…

20_Inception V3深度学习图像分类算法

回顾GoogleNet:传送门 1.1 介绍 InceptionV3是Google开发的一种深度卷积神经网络架构&#xff0c;它是Inception系列网络中的第三代模型&#xff0c;由Christian Szegedy等人在论文《Rethinking the Inception Architecture for Computer Vision》中提出&#xff0c;该论文发…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验17 开放最短路径优先OSPF

一、实验目的 1.验证OSPF协议的作用&#xff1b; 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实验内容 1.构建网络拓扑&#xff1b; 2.验证OSPF协议的作用。 四、实验步骤 1.构建网…

文件操作和IO流

前言&#x1f440;~ 上一章我们介绍了多线程进阶的相关内容&#xff0c;今天来介绍使用java代码对文件的一些操作 文件&#xff08;file&#xff09; 文件路径&#xff08;Path&#xff09; 文件类型 文件操作 文件系统操作&#xff08;File类&#xff09; 文件内容的读…

C语言-预处理详解

文章目录 &#x1f3af;引言&#x1f453;预处理详解1.预定义符号1.1 __FILE__1.2 __LINE__1.3 __DATE__1.4 __TIME__1.5 __STDC__ 2.#define定义常量2.1 定义数值常量2.2 定义字符串常量 3.#define中使用参数3.1**使用示例**3.2注意事项 4.宏替换的规则5.宏函数和函数的对比5.…

基于Netty的自研流系统缓存实现挑战: 内存碎片与OOM困境

01 前言 Kafka 作为流处理平台&#xff0c;在实时流计算和在线业务场景&#xff0c;追尾读追求端到端低延迟。在离线批处理和削峰填谷场景&#xff0c;数据冷读追求高吞吐。两个场景都需要很好的数据缓存设计来支撑&#xff0c;Apache Kafka 的数据存储在本地文件&#xff0c…

从零开始学习嵌入式----C语言框架梳理与后期规划

目录 一、环境搭建. 二、见解 三、C语言框架梳理 四、嵌入式学习规划流程图&#xff08;学习顺序可能有变&#xff09; 一、环境搭建. C语言是一门编程语言&#xff0c;在学习的时候要准备好环境。我个人比较喜欢用VS,具体怎么安装请百度。学习C语言的时候&#xff0c;切忌…

Qt:12.输入类控件(QSpinBox-整数值输入的小部件、QDateEdit、QTimeEdit、QDateTimeEdit- 日期和时间输入的控件)

目录 一、QSpinBox-整数值输入的小部件&#xff1a; 1.1QSpinBox介绍&#xff1a; 1.2属性介绍&#xff1a; 1.3通用属性介绍&#xff1a; 1.4信号介绍&#xff1a; 二、QDateEdit、QTimeEdit、QDateTimeEdit- 日期和时间输入的控件&#xff1a; 2.1QDateEdit、QTimeEdit…

一、YOLO V10安装、使用、训练大全

YOLO V10安装、使用、训练大全 一、下载官方源码二、配置conda环境三、安装YOLOV10依赖四、使用官方YOLO V10模型1.下载模型2.使用模型2.1 图片案例 五、制作数据集1.数据集目录结构2.标注工具2.1 安装标注工具2.2 运行标注工具2.3 设置自动保存2.4 切换yolo模式2.5 开始标注2.…

【C++ | 继承】C++的继承详解 及 例子源码演示

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 本文未经允许…

C++视觉开发 七.模板匹配

模板匹配是一种基于图像处理的技术&#xff0c;用于在目标图像中寻找与给定模板图像最相似的部分。通过设定的模板&#xff0c;将目标图像与模板图像比较&#xff0c;计算其相似度&#xff0c;实现对目标图像的判断。 目录 一.手写数字识别 重要函数&#xff1a; 1.cv::glob…

Mac平台虚拟机 Parallels Desktop v19.4.1,支持M1/M2/M3芯片组

Parallels Desktop for Mac是功能强大灵活度高的虚拟化方案&#xff0c;无需重启即可在同一台电脑上随时访问Windows和Mac两个系统上的众多应用程序。从仅限于PC的游戏到生产力软件&#xff0c;Parallels Desktop都能帮您实现便捷使用。Parallels Desktop 是一款专业的Mac虚拟机…

虚拟机因断电进入./#状态解决办法

现象&#xff1a; 解决&#xff1a;先查看错误日志&#xff1a;journalctl -p err -b查看自己虚拟机中标黄部分的名字 之后运行&#xff1a;xfs_repair -v -L /dev/sda #这里sda用你自己标黄的 最后重启 reboot 即可。

ArcGIS的智慧与情怀

初识ArcGIS 在这个信息化的时代&#xff0c;ArcGIS如同一位智者&#xff0c;静静地伫立在地理信息系统的巅峰。初识它时&#xff0c;我仿佛走进了一片未知的领域&#xff0c;心中充满了好奇与期待。ArcGIS&#xff0c;这款专业的地理信息系统软件&#xff0c;凭借其强大的功能…