在服务器密钥交换中使用私钥计算签名

Posted

技术标签:

【中文标题】在服务器密钥交换中使用私钥计算签名【英文标题】:Compute a signature with private key in Server Key Exchange 【发布时间】:2022-01-05 22:59:28 【问题描述】:

在https://tls.ulfheim.net/ 有一个示例显示如何在“服务器密钥交换”部分计算签名。

https://i.ibb.co/Y7fbkDw/1.jpg(这张图片显示了我所指网站上的服务器密钥交换部分。无法在这篇文章中嵌入图片。)

无论我尝试什么,我都没有得到与该网站上相同的输出,我不明白为什么。

我尝试以两种不同的方式存储相同的数据,然后使用他们在示例中使用的相同 openssl 命令。没有一种方法给出相同的输出。

方法一。

char hex[] =  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x20, 0x9f, 0xd7, 0xad, 0x6d, 0xcf, 0xf4, 0x29, 0x8d, 0xd3, 0xf9, 0x6d, 0x5b, 0x1b, 0x2a, 0xf9, 0x10, 0xa0, 0x53, 0x5b, 0x14, 0x88, 0xd7, 0xf8, 0xfa, 0xbb, 0x34, 0x9a, 0x98, 0x28, 0x80, 0xb6, 0x15 ;
ofstream myfile("c:/hex1.txt", ios::binary);
myfile.write(hex, sizeof hex);

然后:

openssl dgst -hex -sign server.key -sha256 hex1.txt

方法二。

我将这些数据存储在 hex2.txt(ASCII 格式)中:

\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x20\x9f\xd7\xad\x6d\xcf\xf4\x29\x8d\xd3\xf9\x6d\x5b\x1b\x2a\xf9\x10\xa0\x53\x5b\x14\x88\xd7\xf8\xfa\xbb\x34\x9a\x98\x28\x80\xb6\x15

然后:

openssl dgst -hex -sign server.key -sha256 hex2.txt

【问题讨论】:

【参考方案1】:

方法一

你漏掉了curve_info。 applicable RFC 4492 section 5.4 为 TLS1.2 更新的 RFC 5246 appendix A.7 实际上定义了要结束的签名 client_random + server_random + SKX_params 其中 SKX_params 类型为 ServerECDHParams 并由 ECParameters curve_paramsECPoint public 组成 - 这些是 ulfheim标签曲线信息和公钥。

有了正确的数据,我得到了正确的结果:

$ od -tx1 70148855.bin
0000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0000020 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
0000040 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
0000060 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
0000100 03 00 1d 20 9f d7 ad 6d cf f4 29 8d d3 f9 6d 5b
0000120 1b 2a f9 10 a0 53 5b 14 88 d7 f8 fa bb 34 9a 98
0000140 28 80 b6 15
$ openssl sha256 <70148855.bin -sign $privkey -hex
(stdin)= 0402b661f7c191ee59be45376639bdc3d4bb81e115ca73c8348b525b0d2338aa144667ed9431021412cd9b844cba29934aaacce873414ec11cb02e272d0ad81f767d33076721f13bf36020cf0b1fd0ecb078de1128beba0949ebece1a1f96e209dc36e4fffd36b673a7ddc1597ad4408e485c4adb2c873841249372523809e4312d0c7b3522ef983cac1e03935ff13a8e96ba681a62e40d3e70a7ff35866d3d9993f9e26a634c81b4e71380fcdd6f4e835f75a6409c7dc2c07410e6f87858c7b94c01c2e32f291769eacca71643b8b98a963df0a329bea4ed6397e8cd01a110ab361ac5bad1ccd840a6c8a6eaa001a9d7d87dc3318643571226c4dd2c2ac41fb

已添加: 顺便说一句,这仅适用于 TLS1.2 及更低版本中用于 RSA 的签名方案,即 PKCS1v1 中的“块类型 1”方案,现在是 RSASSA-PKCS1-v1_5在 PKCS1v2 中,是确定性的。大多数数字签名方案都不是,包括 TLS1.3 中使用的 RSA-PSS 方案,您无法通过将签名与另一个签名进行比较来检查或测试签名。只能使用方案提供的验证方式。

方法二

完全不正确。 \x00 等是用于 C 和 C++(如您在方法 1 中所做的那样)以及一些其他语言(如 Java、JS/ES 和 Python)以及某些工具的源代码中的符号就像 Unix 中的 printf 命令和 awk 程序一样。但它在其他地方不起作用,特别是在 OpenSSL 读取的文件中不起作用(至少对于数据;它可能在配置文件中起作用,我必须检查)。您的方法二(散列和)标记字节 0x5c 0x78 0x30 0x30 0x5c 0x78 0x30 0x31 代表字符 \ x 0 0 \ x 0 1 等,而不是字节 0x00 0x01 等,不出所料,这是完全不同和错误的。

【讨论】:

以上是关于在服务器密钥交换中使用私钥计算签名的主要内容,如果未能解决你的问题,请参考以下文章

WCF 错误:“证书“我的证书”可能没有能够进行密钥交换的私钥

08.openssl非对称加密算法指令

Diffie-Hellman密钥交换

DH 迪菲-赫尔曼密钥交换

https通信过程及密钥交换

Java笔记-DH密钥交换