当前位置: 首页 > news >正文

别再只抓包了!手把手教你用OpenSSL验证‘挑战-响应’身份鉴别的签名(附完整数据包分析)

从Hex到真相:OpenSSL实战验证挑战-响应签名全流程

当你面对一长串十六进制数据时,是否曾感到无从下手?作为安全工程师,我们经常需要验证各种协议中的数字签名,但大多数教程只停留在理论层面。本文将带你深入TLS握手背后的密码学世界,用OpenSSL命令行工具完成一次完整的挑战-响应签名验证。

1. 准备工作:理解挑战-响应机制

在TLS握手过程中,服务器通过发送数字签名来证明其拥有私钥。这个签名是对特定数据的加密哈希值,通常包括:

  • 客户端随机数(ClientHello.random)
  • 服务端随机数(ServerHello.random)
  • 服务器证书

验证这个签名需要三个关键步骤:

  1. 重建签名原文:按照协议规范拼接原始数据
  2. 提取公钥:从服务器证书中获取验证签名的公钥
  3. 执行验签:使用公钥验证签名有效性

注意:不同TLS版本和密码套件可能使用不同的签名算法,本文以常见的ECDSA为例。

2. 数据提取与处理

2.1 解析网络抓包数据

假设我们已经通过Wireshark等工具捕获了TLS握手流量,并提取出以下关键字段:

# 客户端随机数 f81ce4d345466f00852fd30dc0555086544391bd2bd0ca13b8b66776a0bbc2ab # 服务端随机数 5ed8968e7d19162fdc1aca131ddf438b55275de556c9994a8ff3bb871393d4cd # 服务器证书(DER格式) 30820221308201c6a003020102020108300a06082a811ccf55018375308187310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310d300b060355040a0c04424a4341310d300b060355040b0c04424a43413116301406035504030c0d424a4341534d32544553544341311e301c06092a864886f70d010901160f737570706f727440626a63612e636e301e170d3230303531323035313231345a170d3330303332313035313231345a30818e310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310d300b060355040a0c04424a4341310d300b060355040b0c04424a4341311d301b06035504030c14626a6361736d3273657276657273727031656e63311e301c06092a864886f70d010901160f737570706f727440626a63612e636e3059301306072a8648ce3d020106082a811ccf5501822d03420004a0e54d33742636210e37a36c6e0102c296813a1812d112e44864337d7a248a6865afe51abf3830971465bdcbc9b003c72e62e0c7ca6ce53cf56f265ae877c442a31a301830090603551d1304023000300b0603551d0f040403020430300a06082a811ccf5501837503490030460221009dd093c169af50fbca6061ed1b10d4394b2768d115027f64533f24080d94f20d022100cc96806594a6ad537b78991c6e673384ef415da8c0d226103dcee21327341032 # 签名值 3045022100e4795b5a947526f8e7cbd0edd571ea8749e0efd24323799346ea2c740c006c5a0220026189e51c19d20d40a82606d0ed72cb9530a189bbb94c09e4559d7d8ff3f598

2.2 构建签名原文

根据TLS 1.2规范,签名原文的构成顺序为:

  1. 客户端随机数(32字节)
  2. 服务端随机数(32字节)
  3. 证书长度(3字节)
  4. 证书本身

使用xxd工具将十六进制转换为二进制文件:

# 将客户端随机数保存为文件 echo -n "f81ce4d345466f00852fd30dc0555086544391bd2bd0ca13b8b66776a0bbc2ab" | xxd -r -p > client_random.bin # 将服务端随机数保存为文件 echo -n "5ed8968e7d19162fdc1aca131ddf438b55275de556c9994a8ff3bb871393d4cd" | xxd -r -p > server_random.bin # 计算证书长度并保存 echo -n "000225" | xxd -r -p > cert_len.bin # 将证书保存为文件 echo -n "30820221308201c6a003020102020108300a06082a811ccf55018375308187310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310d300b060355040a0c04424a4341310d300b060355040b0c04424a43413116301406035504030c0d424a4341534d32544553544341311e301c06092a864886f70d010901160f737570706f727440626a63612e636e301e170d3230303531323035313231345a170d3330303332313035313231345a30818e310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310d300b060355040a0c04424a4341310d300b060355040b0c04424a4341311d301b06035504030c14626a6361736d3273657276657273727031656e63311e301c06092a864886f70d010901160f737570706f727440626a63612e636e3059301306072a8648ce3d020106082a811ccf5501822d03420004a0e54d33742636210e37a36c6e0102c296813a1812d112e44864337d7a248a6865afe51abf3830971465bdcbc9b003c72e62e0c7ca6ce53cf56f265ae877c442a31a301830090603551d1304023000300b0603551d0f040403020430300a06082a811ccf5501837503490030460221009dd093c169af50fbca6061ed1b10d4394b2768d115027f64533f24080d94f20d022100cc96806594a6ad537b78991c6e673384ef415da8c0d226103dcee21327341032" | xxd -r -p > cert.der # 拼接所有文件形成签名原文 cat client_random.bin server_random.bin cert_len.bin cert.der > signature_input.bin

3. 证书与公钥提取

3.1 解析DER格式证书

使用OpenSSL查看证书信息:

openssl x509 -inform der -in cert.der -text -noout

关键输出包括:

  • 签名算法:ecdsa-with-SHA256
  • 公钥信息:
    Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:a0:e5:4d:33:74:26:36:21:0e:37:a3:6c:6e:01: 02:c2:96:81:3a:18:12:d1:12:e4:48:64:33:7d:7a: 24:8a:68:65:af:e5:1a:bf:38:30:97:14:65:bd:cb: c9:b0:03:c7:2e:62:e0:c7:ca:6c:e5:3c:f5:6f:26: 5a:e8:77:c4:42:a3

3.2 提取公钥

将公钥保存为PEM格式:

openssl x509 -inform der -in cert.der -pubkey -noout > pubkey.pem

查看公钥文件内容:

-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoOVNM3QmNiEON6NsbgECwpaBOhgS 0RLkSGQzfXokimhlr+UavzgwlxRlvcvJsAPHLmLgx8ps5Tz1byZa6HfEQqM= -----END PUBLIC KEY-----

4. 签名验证实战

4.1 准备验证材料

我们已经拥有:

  • 签名原文(signature_input.bin)
  • 签名值(原始十六进制)
  • 公钥(pubkey.pem)

首先将签名值保存为文件:

echo -n "3045022100e4795b5a947526f8e7cbd0edd571ea8749e0efd24323799346ea2c740c006c5a0220026189e51c19d20d40a82606d0ed72cb9530a189bbb94c09e4559d7d8ff3f598" | xxd -r -p > signature.bin

4.2 执行验签命令

使用OpenSSL的dgst命令进行验证:

openssl dgst -sha256 -verify pubkey.pem -signature signature.bin signature_input.bin

成功验证的输出应为:

Verified OK

4.3 常见问题排查

如果验证失败,可能的原因包括:

  1. 签名原文拼接错误

    • 检查各字段顺序是否正确
    • 确认证书长度字段是否为3字节
  2. 签名算法不匹配

    • 确保使用的哈希算法与证书中声明的算法一致
    • 对于ECDSA签名,尝试不同的哈希算法(SHA256/SHA384等)
  3. 证书链问题

    • 验证证书是否过期或被吊销
    • 检查中间证书是否完整

5. 深入理解签名结构

5.1 ECDSA签名解析

ECDSA签名本身是ASN.1编码的,包含两个大整数r和s。我们可以解析签名内容:

openssl asn1parse -inform der -in signature.bin

输出示例:

0:d=0 hl=2 l= 69 cons: SEQUENCE 2:d=1 hl=2 l= 33 prim: INTEGER :E4795B5A947526F8E7CBD0EDD571EA8749E0EFD24323799346EA2C740C006C5A 37:d=1 hl=2 l= 32 prim: INTEGER :26189E51C19D20D40A82606D0ED72CB9530A189BBB94C09E4559D7D8FF3F598

5.2 手动验证步骤

对于希望更深入理解的技术人员,可以分步验证:

  1. 计算签名原文的SHA256哈希:

    openssl dgst -sha256 -binary signature_input.bin > hash.bin
  2. 提取r和s值:

    openssl asn1parse -inform der -in signature.bin -strparse 2 -noout -out r.bin openssl asn1parse -inform der -in signature.bin -strparse 37 -noout -out s.bin
  3. 使用低级别EC命令验证:

    openssl pkeyutl -verify -in hash.bin -sigfile signature.bin -pubin -inkey pubkey.pem

6. 自动化脚本实现

为提高效率,可以创建自动化验证脚本:

#!/bin/bash # 输入参数 CLIENT_RANDOM="f81ce4d345466f00852fd30dc0555086544391bd2bd0ca13b8b66776a0bbc2ab" SERVER_RANDOM="5ed8968e7d19162fdc1aca131ddf438b55275de556c9994a8ff3bb871393d4cd" CERT="30820221308201c6a003020102020108300a06082a811ccf55018375308187310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310d300b060355040a0c04424a4341310d300b060355040b0c04424a43413116301406035504030c0d424a4341534d32544553544341311e301c06092a864886f70d010901160f737570706f727440626a63612e636e301e170d3230303531323035313231345a170d3330303332313035313231345a30818e310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310d300b060355040a0c04424a4341310d300b060355040b0c04424a4341311d301b06035504030c14626a6361736d3273657276657273727031656e63311e301c06092a864886f70d010901160f737570706f727440626a63612e636e3059301306072a8648ce3d020106082a811ccf5501822d03420004a0e54d33742636210e37a36c6e0102c296813a1812d112e44864337d7a248a6865afe51abf3830971465bdcbc9b003c72e62e0c7ca6ce53cf56f265ae877c442a31a301830090603551d1304023000300b0603551d0f040403020430300a06082a811ccf5501837503490030460221009dd093c169af50fbca6061ed1b10d4394b2768d115027f64533f24080d94f20d022100cc96806594a6ad537b78991c6e673384ef415da8c0d226103dcee21327341032" SIGNATURE="3045022100e4795b5a947526f8e7cbd0edd571ea8749e0efd24323799346ea2c740c006c5a0220026189e51c19d20d40a82606d0ed72cb9530a189bbb94c09e4559d7d8ff3f598" # 临时文件 TMP_DIR=$(mktemp -d) trap 'rm -rf "$TMP_DIR"' EXIT # 构建签名原文 echo -n "$CLIENT_RANDOM" | xxd -r -p > "$TMP_DIR/client_random.bin" echo -n "$SERVER_RANDOM" | xxd -r -p > "$TMP_DIR/server_random.bin" echo -n "$CERT" | xxd -r -p > "$TMP_DIR/cert.der" CERT_LEN=$(printf "%06x" $(stat -c%s "$TMP_DIR/cert.der")) echo -n "${CERT_LEN:0:6}" | xxd -r -p > "$TMP_DIR/cert_len.bin" cat "$TMP_DIR/client_random.bin" "$TMP_DIR/server_random.bin" "$TMP_DIR/cert_len.bin" "$TMP_DIR/cert.der" > "$TMP_DIR/signature_input.bin" # 提取公钥 echo -n "$CERT" | xxd -r -p | openssl x509 -inform der -pubkey -noout > "$TMP_DIR/pubkey.pem" # 准备签名文件 echo -n "$SIGNATURE" | xxd -r -p > "$TMP_DIR/signature.bin" # 执行验证 openssl dgst -sha256 -verify "$TMP_DIR/pubkey.pem" -signature "$TMP_DIR/signature.bin" "$TMP_DIR/signature_input.bin"

在实际渗透测试中,这种签名验证技术可以帮助确认服务器身份的真实性,检测中间人攻击,以及验证各种安全协议的正确实现。掌握这些底层操作不仅能加深对协议的理解,还能在遇到非常规情况时快速定位问题。

http://www.cnnetsun.cn/news/2194085.html

相关文章:

  • Python大模型微调不是调参,是系统工程:我们实测了12种量化+微调组合,最终锁定BF16+NF4+GA=2的最优性价比方案
  • 从逆波兰表达式到自制脚本引擎:用C++实现eval()的踩坑与优化实录
  • 终极GlosSI使用指南:让Steam控制器在任何游戏中都能工作
  • 文档重排技术演进与jina-reranker-v3架构解析
  • 别再只测电压了!手把手教你用LTC2944库仑计给锂电池做精准电量监控(附完整Arduino代码)
  • 开箱即用的Docker开发环境:lean-ctx镜像深度解析与实战指南
  • 电感Q值详解:影响谐振电路性能的关键因素
  • 5个简单步骤掌握GlosSI:解锁全平台游戏控制器配置终极指南
  • 5步构建RE引擎游戏Mod:从零开始掌握REFramework开发
  • Appium MCP Server:用自然语言驱动移动端自动化测试
  • 从医学影像到AI模型:我是如何用LIDC-IDRI数据集构建肺癌分类项目第一阶段的
  • taotoken为独立开发者提供稳定可靠的大模型api服务
  • 终极风扇控制方案:FanControl让Windows散热管理如此简单
  • 从数学证明到数据可视化:用Manim CE 0.7制作‘会讲故事’的技术视频
  • CentOS7服务器运维:用yum源管理多版本Golang(稳定版与RC版)实战
  • YimMenu终极指南:如何打造GTA5最强防护与游戏增强体验
  • 从《原神》模型到Unity特效:手把手教你拆解‘消融为灰’的两种ShaderGraph实现方案
  • 高压均质机HPH构造详解:三大核心模块
  • 【FreeRTOS+STM32 C语言深度优化】:仅改11行关键代码,系统吞吐量翻倍、栈溢出归零的工业级方案
  • 体验 Taotoken 官方价折扣活动如何降低个人开发者的模型使用成本
  • 保姆级教程:用PaddlePaddle高层API搞定MNIST手写数字识别(从数据集到推理)
  • 你的用户真的‘活跃’吗?用RFE模型重新定义并精细化运营你的用户分层
  • 别再乱用GiveAbility了!深入理解UE5 GAS中GameplayAbility的激活(Activate)与应用(Give)核心机制
  • 抖音内容下载架构设计与生产环境部署指南:基于Python的高效批量下载解决方案
  • 从嵌入式到云端:手把手教你用Paho和libmosquitto搞定C/C++ MQTT客户端(附心跳、重连配置)
  • 从`[1]`到`(Author, 2023)`:详解如何在LaTeX中为Elsevier期刊定制参考文献引用样式(以EJOR为例)
  • 用Python的scikit-fuzzy库,手把手教你实现一个智能洗衣机模糊控制器
  • 3步快速安装Video DownloadHelper CoApp伴侣应用:完整使用指南
  • Obsidian Zettelkasten模板:3步构建你的第二大脑知识系统
  • 通过 OpenClaw 配置 Taotoken 作为 Agent 工作流后端的详细教程