如何从公钥生成派生共享密钥

问题描述 投票:0回答:1

我正在对一个应用程序进行逆向工程。 我注意到,在这个应用程序的一部分中,向服务器发出了一个请求,并从服务器接收了一个 base64 格式的密钥。 然后它将相同的密钥转换为十六进制格式,然后从中派生并创建另一个名为共享密钥的密钥。 然后,它将此密钥用于 AES 方法中的对称加密操作。 我想知道这个推导的算法是怎样的,以及如何从主密钥字符串得到派生密钥字符串,这称为共享密钥。

从服务器接收的主密钥 base64:BEdGgIH9PLFU2BcF41Uqvn38inO3bBHbUwKcAIJRBAnf+hfiZo4hWogn8eqVHBCzjdtxmzieFEuRpqi8NRlWH6o=

将 base64 密钥转换为十六进制格式:0447468081fd3cb154d81705e3552abe7dfc8a73b76c11db53029c0082510409dffa17e2668e215a8827f1ea951c10b38ddb719b389e14 4b91a6a8bc3519561faa

派生密钥:7e2f725debc83adafe237b95ed5cf1c9a8b16e25b83848049ecbd4a85b38f000

我在 javascript 中找到了这个应用程序的一些代码,我跟踪这些代码以生成共享密钥 在我想要的系统(JavaScript 语言)中执行此操作的代码如下:

let a = '0447468081fd3cb154d81705e3552abe7dfc8a73b76c11db53029c0082510409dffa17e2668e215a8827f1ea951c10b38ddb719b389e144b91a6a8bc3519561faa';
n = d.keyFromPublic(a, "hex");
s = e.derive(n.getPublic());
r = s.toString(16); 
//after run this code r is 7e2f725debc83adafe237b95ed5cf1c9a8b16e25b83848049ecbd4a85b38f000
now r is a hex and use for AES.

另外,在代码中可以看到“secp256k1”这几个词,我觉得跟这个操作的方法和算法有关

这些代码到底做了什么?如何以及在什么操作中导出主键,然后我们得到第二个键? 感谢您提供有关此操作的解释

cryptography reverse-engineering elliptic-curve node-crypto secp256k1
1个回答
0
投票

正如评论中已经提到的,这似乎是一个 ECDH(椭圆曲线 Diffie-Hellman)密钥交换

在 Diffie-Hellman 密钥交换中,有两个参与者:在您的情况下是应用程序和服务器。每个参与者都有一个密钥对,由私钥和相应的公钥组成。参与者互相发送他们的公钥,但从不泄露他们的私钥。每个参与者都进行计算

calc(my_private_key, their_public_key)
,其输出是一个称为shared secret的字节串。 Diffie-Hellman 的非凡之处在于,尽管两个参与者进行不同的计算,但输出是相同的:数学属性确保
calc(application_private_key, server_public_key)
(在应用程序中计算)给出与
calc(server_private_key, application_public_key)
(在应用程序中计算)相同的结果服务器)。

参与者必须就达成一致;对于椭圆曲线变体,该组称为 curve。函数

calc
需要知道这个组;它可以在一个或两个键参数中编码,也可以作为单独的参数传递。 Secp256k1 是一种受到广泛支持的曲线(最受加密货币欢迎),因此您的应用程序很可能始终使用该特定曲线。

对于secp256k1,私钥和共享密钥都是256位的数字,按照惯例按照little-endian顺序表示为32字节的字符串。公钥是一对 256 位数字。您将公钥编码为 65 字节的字符串,其中第一个字节为 0x04;这是最常见的公钥编码,由字节 0x04 和后面的两个数字组成(每个数字以小端格式编码为 32 字节),通常称为“未压缩点”格式1.

您可以通过调用任何加密库的 ECDH 函数生成相同的共享密钥,将曲线

secp256k1
、您的应用程序的私钥和服务器的公钥传递给它。如果您需要生成自己的私钥,该库将具有相应的功能;再次需要曲线上的 ECC 密钥
secp256k1
。如果您需要将相应的公钥发送到服务器,同样,库将有一个函数从私钥对象中获取它(或者将公钥公开为一个单独的对象)。

共享秘密不应该直接用作对称密钥:它应该传递给密钥派生函数。但这是许多应用程序都会犯的一个相对良性的设计错误(而且它不太可能被实际利用)。因此,您的应用程序很可能直接使用共享密钥的前 16 个字节作为 AES 密钥。

1 以这种方式调用是因为可以从其中一个和一个额外的位中恢复这两个数字——这被称为“压缩点”。但是由于您已经有一个未压缩的点,因此您不太可能需要担心压缩点。

© www.soinside.com 2019 - 2024. All rights reserved.