物联网安全系列 - 非对称加密算法 ECDH

2023-05-16

非对称加密算法 - ECDH

背景

   之前的章节讲到了对称加密算法AES,发送方和接收方需要使用相同的密钥进行通讯,但是发送方怎么将密钥安全的发送给接收方?这是一个问题。

密钥分配问题

   对称加密算法中,为了将密钥安全的发送给对端,通常有以下四种方法:

  1. 事先共享密钥
       事先双方约定好密钥的数值,或者使用其他安全的手段例如派特工押送等,将密钥安全的送到对端,这种方式虽然简单,但是局限性很大,另外通讯量增大以后,密钥个数也会相应增加,这在高数量级的设备通讯上并不现实。

  2. 密钥分配中心
       为了解决事先共享密钥的密钥增多的问题,也可以使用密钥分配中心来解决。每次加密的密钥由密钥中心进行分配,每个人只要和密钥中心事先共享密钥就可以了。虽然这个方法解决了密钥增多的问题,但是密钥中心存储和记录了所有的密钥,一旦它出现故障或者被攻击破坏,那么所有的加密都会瘫痪,这也是集中式管理的缺点。

  3. DH 密钥交换
       为了解决集中式管理的缺点,有人想出了 Diffie-Hellman 密钥交换的方法。在 Diffie-Hellman 密钥交换中,加密通信双方需要交换一些信息,而这个过程是可以防止窃听者攻击的。根据交换的信息,双方各自生成相同的密钥。而窃听者无法生成相同的密钥。 将DH算法与ECC公钥算法结合形成ECDH算法,这是一种解决密钥交换问题的一种很常见的解决方案,这个下面也会详细讲解。

  4. 非对称加密
       非对称加密双方分别有一个公钥和一个私钥。公钥可以互相发给对方,用来加密数据,私钥则由自己保存。公钥甚至在网上传播,被窃听者拿到也没有关系,由于没有私钥,他也无法解开密文。私钥只要掌握在接收者手上就不会导致密文被窃听,这样就解决了密钥传输的问题。

  虽然非对称加密解决了密钥配送的问题,但是非对称密钥仍然存在一些问题,比如:

  • 非对称加密处理速度较慢,通常不到对称加密速度的十分之一
  • 无法防止中间人攻击 ,这个通常需要结合签名和证书来解决。

非对称加密算法

   非对称加密算法可以说是密码学历史上最伟大的发明,每个公钥算法的底层原理都是非常巧妙的。常用的非对称加密算法有RSA、ECC算法等, 在物联网领域常用的是ECC加密算法。

非对称加密算法的本质是什么?

   我们知道非对称加密可以防止窃听者攻击,也就是说双方进行公钥分享、协商、计算的时候就算是旁边有窃听者,将双方的数据都获取到,也无法计算出双方协商的密钥。 对于初学者可能很难理解这件事情,双方的数据都可以窃听到,为什么通讯双方可以计算出密钥,而窃听者却无法计算出呢?

  • 对于RSA算法是基于大素数相乘后结果很容易计算,但是通过结果反推出两个素数却很困难,目前只能使用穷举法。

  • ECC算法是基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点G,并选取一个整数k,求解K=kG很容易,但反过来计算确很困难。

所以非对称加密的本质就是利用正向运算比较简单,但可逆运算比较困难的单向函数。 而防止窃听者攻击也并不是窃听者完全无法破解出密钥,而是因为窃听者只能使用穷举法破解,可能破解的时间是正向运算的几万倍,就近似的认为该算法是可以防止窃听者攻击的。

ECDH 算法简介

   由于 ECC 密钥具有很短的长度,所以运算速度比较快。到目前为止,对于 ECC 进行逆操作还是很难的,数学上证明不可破解,ECC 算法的优势就是性能和安全性高。实际应用可以结合其他的公开密钥算法形成更快、更安全的公开密钥算法,比如结合 DH 密钥形成 ECDH 密钥协商算法,结合数字签名 DSA 算法组成 ECDSA 数字签名算法。

   ECDH算法常常用来进行密钥的协商,协商好密钥后,用来解决上面的密钥分配问题,将对称加密的密钥安全的传到对端设备。

算法加密/解密数字签名密钥交换
RSA
Diffie-Hellman
DSS
椭圆曲线 ECC

如上表,椭圆曲线可以用于 3 个方面:

  • 基于椭圆曲线的公钥密码
  • 基于椭圆曲线的数字签名
  • 基于椭圆曲线的密钥交换

ECDH 算法原理

椭圆曲线源自于求椭圆弧长的椭圆积分的反函数。一般情况下,椭圆曲线可以用下面的方程式来表示,其中 a,b,c,d 为系数:

E: y^2 = ax^3 + bx^2 + cx+ d

举个例子,

上面是一条椭圆曲线,但是它的样子也并不是一个椭圆。

1. 椭圆曲线上的运算

加法运算:椭圆曲线上的两点 A 和 B,构成的直线与椭圆曲线的交点,与 X 轴的对称点,定义为 A+B。如下图:

当然也存在两个点重合的情况,这种情况下,就相当于寻找 2 倍点的问题。在椭圆曲线上的一点 A,做一条切线,与椭圆曲线的另外一交点,相对于 X 轴的对称点成为 2 倍点。这种运算成为 2 倍计算,如下图:

点 A 相对于 X 轴的对称位置的点成为 -A。这个运算成为椭圆曲线的正负取反运算。如下图:

2. 椭圆曲线加密实质

椭圆曲线加密的实质是利用椭圆曲线上离散对数问题(Elliptic Curve Discrete Logarithm Problem, ECDLP),实质是已知点 xG 求数 x 的问题

已知:
椭圆曲线 E
椭圆曲线 E 上的一点 G (基点)
椭圆曲线 E 上的一点 xG (G 的 x 倍)

求:
数 x

椭圆曲线在实数域上是连续的,曲线也是一条光滑的曲线。假设椭圆曲线为 E2:y^2 = x^3 + x + 1,如下图:

如果位于有限域 F23 上,那么 E2:y^2 ≡ x^3 + x + 1 (mod 23)。此时椭圆曲线就不是一个连续的曲线了,而是一堆离散的点。如下图:

上图中每个点的 y 坐标对 23 求余,都等于 x^3 + x + 1 对 23 求余。如果我们把 E2 上的点 G=(0,1) 作为基点,那么按照椭圆曲线的计算规则计算 2G、3G、4G、5G、……。

这就是“已知 G 和 xG 求 x 的问题”。这个问题在 p 相当大的时候,很难求解。椭圆曲线无法被破解的原因是:求解椭圆曲线上的离散对数问题是非常困难的

但是椭圆曲线加密算法并非在实数域 R 上,而是在有限域 F§ 上。有限域 F§ 指的是对于某个给定的质数 p,由 0,1,2,……,p-1 共 p 个元素所组成的整数集合中定义的加减乘除运算。

椭圆曲线加密算法除了可以使用特征数为质数 p 的素域 GF§,椭圆曲线还可以使用特征数为 2^m 的扩张域 GF(2^m)。

3. 椭圆曲线 Diffie-Hellman 密钥交换 (ECDH)

非椭圆曲线的 Diffie-Hellman 密钥交换利用的是:

以 p 为模,已知 G 和 G^x mod p 求 x 的复杂度(有限域上的离散对数问题)

椭圆曲线的 Diffie-Hellman 密钥交换利用的是:

在椭圆曲线上,已知 G 和 xG 求 x 的复杂度(椭圆曲线上的离散对数问题)

DH 算法和 RSA 算法最大的不同在于:

  • DH 算法在进行密钥协商的过程中,通信双方的任何一方无法独自计算出一个会话密钥,通信双方各自保留一部分关键信息,再将另外一部分信息告诉对方,双方有了全部信息才能共同计算出全部的会话密钥。
  • RSA 算法在传输会话密钥的时候,会话密钥完全由客户端生成和控制,并没有服务端的参与,准确的来说应该叫 RSA 密钥传输

举个例子来说明 ECDH 算法是如何生成共享密钥的。

  • Alice 向 Bob 发送点 G,点 G 被窃听了也没有关系。
  • Alice 生成随机数 a。这个数只有 Alice 自己一个人知道。也没有必要告诉 Bob。更加不能让第三者知道,这个 a 称为 Alice 的私钥。
  • Bob 生成随机数 b。这个数只有 Bob 自己一个人知道。也没有必要告诉 Alice。更加不能让第三者知道,这个 b 称为 Bob 的私钥。
  • Alice 向 Bob 发送点 aG。点 aG 被窃听了也没有关系。它是 Alice 的公钥。
  • Bob 向 Alice 发送点 bG。点 bG 被窃听了也没有关系。它是 Bob 的公钥。
  • Alice 拿到 Bob 发过来的 bG,开始计算其在椭圆曲线上 a 倍的点,即 a(bG) = abG,它就是 Alice 和 Bob 的共享密钥。
  • Bob 拿到 Alice 发过来的点 aG 开始计算其在椭圆曲线上 b 倍的点,即 b(aG) = baG = abG,它就是 Alice 和 Bob 的共享密钥。

窃听者一共可以拿到 3 个有效信息:G、aG、bG。但是由于“已知 G 和 xG 求 x 非常难”,导致已知 G 和 aG 无法求解出 a,已知 G 和 bG 无法求解出 b。所以最终也就无法求解出私钥 abG。

严格的来说,椭圆曲线上的离散对数问题的复杂度只能证明 “已知 G,aG,bG 难以求出 a,b”,但无法证明“已知 G,aG,bG 难以求出 abG”,后者需要另外证明。具体证明这里省略。

如果采用静态的 DH 算法和 ECC 结合就是 ECDH 算法。这种方式每次都使用的相同的 G 基点,它的优点在于可以避免每次在初始化连接时服务器频繁生成 G。这个过程比较消耗 CPU。但是它带来的缺点是,一旦随机数 a、b 被泄露了,那么在这之前的所有会话都将会被解密。

   为了解决这个问题,于是出现了 DHE 算法(Diffie-Hellman Ephemeral ,短暂临时的 DH 算法),结合 ECC 后形成了 ECDHE 算法。它可以保证每次通信使用的共享密钥都是不同的,DH 密钥对仅仅保存在内存中,不像 RSA 的私钥保存在磁盘上,攻击者即使从内存中破解了私钥,也仅仅影响本次通信,所以无需担心在此之前的通信内容会被解密,这样的特征成为前向安全性(Forward Secrecy,FS)或者完全前向安全性(Perfect Forward Secrecy,PFS)。更安全的是,协商出会话密钥后,a 和 b 两个私钥可以丢弃,进一步提升了安全性,在有限的时间、有效的空间生成了密钥对。在 TLS 握手中使用的 ECDHE_ECDSA 和 ECDHE_RSA 密钥交换算法。

混合加密系统

通过使用对称加密可以解决信息安全的问题,但是使用对称加密,必须要解决密钥配送的问题。

使用公钥密码可以解决密钥配送的问题,但是公钥密码又暴露了 2 个新的问题。

  • 公钥密码的处理速度远远低于对称密码
  • 公钥密码难以抵御中间人攻击

第一点缺点可以用这一章节讲的混合加密系统来解决。第二点缺点需要用到下一篇文章中的认证相关的算法来解决。

混合密码系统 (hybrid crytosystem) 是将对称密码和公钥密码的优势相结合的方法。用快速的对称密码对明文进行加密,用公钥密码对对称密码的密钥进行加密。由于对称密钥一般都比消息本身要短,这样公钥密码速度慢的问题也可以忽略。

  • 用对称密码对消息明文进行加密
  • 用伪随机生成器生成对称密码加密中使用的会话密钥
  • 用公钥密码加密会话密钥
  • 从混合密码系统外部赋予公钥密码加密时使用的密钥

会话密钥 (session key) 是指为本次通信而生成的临时密钥。它一般都是通过伪随机数生成器产生的。伪随机生成器所产生的会话密钥同时也会作为对称密码的密钥使用。会话密钥是对称密码的密钥,同时也是公钥密码的明文

下图是混合密码系统中的加密流程:

值得说明的是,公钥密码的强度应该高于对称密码。因为对称密码会话密钥被破译只影响本地通信内容,但是公钥密钥被破译就会影响到过去所有通信内容,以及未来所有通信内容。

下图是混合密码系统中的解密流程:

OpenSSL 中的 ECC

1. DH 密钥协商

与 RSA 密钥对生成方式不一样,DH 密钥对生成方式分为 2 步,第一步先生成参数文件,第二步再根据参数文件生成密钥对,同一个参数文件可以生成无数多且不重复的密钥对

第一步,生成 DH 密钥对

// 生成 2048 比特的参数文件
$ openssl dhparam -out dhparam.pem -2 2048

$ openssl dhparam -in dhparam.pem -noout -C

输出

Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
......................+..........................................................................+..............................................................................................................................................................................................+.......................................................+

#ifndef HEADER_DH_H
# include <openssl/dh.h>
#endif

DH *get_dh2048()
{
    static unsigned char dhp_2048[] = {
	0xBD, 0x70, 0xDB, 0x2E, 0xF9, 0x0B, 0x89, 0x37, 0xC4, 0x31,
	0x93, 0x48, 0x47, 0xEF, 0xD5, 0xEA, 0x7E, 0xBC, 0xDA, 0xC8,
	0x14, 0x0E, 0x82, 0xDD, 0xF6, 0xC6, 0x07, 0x2A, 0xD4, 0x97,
	0xC3, 0x02, 0xA1, 0x9B, 0x02, 0xCB, 0xE4, 0xC0, 0xB9, 0x33,
	0xD1, 0xBB, 0x69, 0xF0, 0xBA, 0x8C, 0x7A, 0x57, 0x1F, 0xDF,
	0xD3, 0xB5, 0x2F, 0x87, 0x1E, 0xA8, 0x35, 0xE4, 0xC0, 0x94,
	0xED, 0x20, 0x04, 0x26, 0x58, 0x50, 0x27, 0xFC, 0xF6, 0xE1,
	0xBE, 0xC7, 0xB8, 0x7A, 0x14, 0xC1, 0x08, 0x16, 0x06, 0xC6,
	0xB8, 0x09, 0xDC, 0x34, 0xEA, 0xA0, 0xD1, 0x3E, 0x88, 0xBD,
	0xB3, 0xBB, 0x05, 0xFE, 0x4D, 0xCB, 0x62, 0x05, 0x9A, 0xC7,
	0x00, 0xA2, 0x0B, 0x73, 0xAD, 0xDD, 0x39, 0x18, 0x9A, 0xD8,
	0x2A, 0x95, 0xCE, 0xF4, 0x10, 0x6A, 0xB2, 0x5C, 0x0F, 0x9E,
	0x99, 0xE5, 0xE6, 0x0D, 0x6C, 0x19, 0xF5, 0xF5, 0xDC, 0x07,
	0x2D, 0xF0, 0xDE, 0xB5, 0x58, 0xEC, 0x35, 0x33, 0xEF, 0x65,
	0x70, 0xC3, 0x8C, 0xBF, 0x14, 0x40, 0x4C, 0xC3, 0x47, 0x77,
	0xE0, 0x5F, 0xF6, 0x61, 0x5F, 0x49, 0x35, 0xCC, 0x39, 0x75,
	0x8E, 0x31, 0xA3, 0x99, 0x43, 0x61, 0xD7, 0xE3, 0xB7, 0xB8,
	0x0F, 0x79, 0xF3, 0x66, 0x50, 0x95, 0x0D, 0x95, 0xB2, 0x5F,
	0x1B, 0x2C, 0x9D, 0x64, 0xE0, 0x54, 0xCB, 0x27, 0xE9, 0x4A,
	0x23, 0x96, 0xA0, 0x7E, 0x55, 0xD4, 0xA9, 0x93, 0x43, 0xB0,
	0x69, 0xB2, 0xF5, 0xB4, 0x9D, 0x41, 0x5B, 0xD3, 0x5D, 0x4B,
	0x91, 0x48, 0x9F, 0xAA, 0x54, 0xA4, 0xA1, 0x81, 0xF1, 0x59,
	0xF6, 0xB3, 0x44, 0x8C, 0xE7, 0x83, 0x8F, 0x57, 0x63, 0x52,
	0x58, 0x70, 0x2F, 0x0A, 0xC1, 0xC0, 0xE5, 0xDD, 0x6F, 0x4D,
	0xFD, 0xC1, 0x5D, 0x61, 0x6E, 0xD0, 0xA4, 0xBD, 0x15, 0xA1,
	0xA6, 0xDE, 0x61, 0xC9, 0xF4, 0x4B
    };
    static unsigned char dhg_2048[] = {
	0x02
    };
    DH *dh = DH_new();
    BIGNUM *dhp_bn, *dhg_bn;

    if (dh == NULL)
        return NULL;
    dhp_bn = BN_bin2bn(dhp_2048, sizeof(dhp_2048), NULL);
    dhg_bn = BN_bin2bn(dhg_2048, sizeof(dhg_2048), NULL);
    if (dhp_bn == NULL || dhg_bn == NULL
            || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn)) {
        DH_free(dh);
        BN_free(dhp_bn);
        BN_free(dhg_bn);
        return NULL;
    }
    return dh;
}
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEAvXDbLvkLiTfEMZNIR+/V6n682sgUDoLd9sYHKtSXwwKhmwLL5MC5
M9G7afC6jHpXH9/TtS+HHqg15MCU7SAEJlhQJ/z24b7HuHoUwQgWBsa4Cdw06qDR
Poi9s7sF/k3LYgWaxwCiC3Ot3TkYmtgqlc70EGqyXA+emeXmDWwZ9fXcBy3w3rVY
7DUz72Vww4y/FEBMw0d34F/2YV9JNcw5dY4xo5lDYdfjt7gPefNmUJUNlbJfGyyd
ZOBUyyfpSiOWoH5V1KmTQ7BpsvW0nUFb011LkUifqlSkoYHxWfazRIzng49XY1JY
cC8KwcDl3W9N/cFdYW7QpL0VoabeYcn0SwIBAg==
-----END DH PARAMETERS-----

第二步,基于参数文件生成密钥对

$ openssl genpkey -paramfile dhparam.pem -out dhkey.pem

// 查看密钥对文件内容
$ openssl pkey -in dhkey.pem -text -noout

输出

DH Private-Key: (2048 bit)
    private-key:
        53:7c:d5:88:80:13:49:b0:c0:00:79:62:fd:4b:8d:
        54:c6:b2:f3:49:45:fa:3c:f7:d8:49:cf:b2:b2:cd:
        b6:45:be:b8:de:54:9b:07:7e:dc:e5:f1:92:0c:7c:
        7d:b9:6e:aa:db:3e:a0:b0:e1:e8:aa:b6:6e:71:c8:
        59:30:b7:75:cb:79:c8:44:25:18:36:2f:22:c2:6b:
        fb:19:f6:31:7e:c8:6d:df:5f:46:cf:b9:df:41:53:
        1c:5e:42:9f:46:77:29:c0:09:a0:a2:4d:e8:f7:44:
        43:1a:f8:43:18:d1:2d:7f:56:75:dc:62:4f:84:93:
        26:c6:fc:ca:a6:5f:50:73:d8:bc:ee:2b:1c:65:22:
        4c:ab:0b:a3:a0:ce:d3:cd:1d:d9:21:3f:b3:32:f0:
        74:fd:3d:98:1d:43:3b:a4:ed:e0:d2:7e:eb:27:64:
        c7:64:54:e7:12:19:5d:f8:f0:a5:fc:15:50:ee:20:
        8f:81:84:b5:e6:ba:64:9a:e0:36:bc:61:09:b3:b3:
        ea:24:63:92:66:13:50:2d:5b:f5:db:2f:15:3d:6b:
        e3:63:99:61:70:8e:b1:12:a1:c1:bb:c0:fa:57:90:
        ae:47:7a:78:35:ce:dc:47:2a:63:b4:30:4a:9d:49:
        4f:2b:ac:a0:8e:47:44:dc:a5:29:68:cd:c6:e0:74:
        50
    public-key:
        00:81:0a:3e:3b:29:8a:e9:1e:26:47:e0:cc:a0:40:
        e9:2d:03:c4:55:64:b0:73:2c:6e:39:6f:5a:95:de:
        a3:44:6a:d1:20:f4:69:68:3c:58:8f:f5:86:94:39:
        13:bf:c7:66:1f:af:7b:1e:0e:15:cd:0e:f9:65:d4:
        d4:70:37:63:50:f7:7b:93:6c:bf:e2:9a:de:fa:41:
        13:20:8b:23:0c:f7:b3:94:00:19:6d:65:f2:30:6a:
        50:88:8f:5e:7e:40:79:fa:14:0f:73:3b:51:ed:24:
        06:5d:29:f9:6e:34:7a:21:6e:b0:cf:6a:7e:c3:26:
        31:3f:f5:42:47:f6:2f:45:c4:89:67:90:b4:69:0e:
        73:92:57:90:32:63:be:77:9f:f1:a8:c5:e3:cd:4d:
        b8:2f:13:4f:88:78:9a:09:1b:04:fa:ab:6d:0c:a7:
        b8:b4:6e:76:05:42:d2:50:b7:a3:6b:0c:94:53:9f:
        fa:eb:9e:20:df:e7:91:a3:08:fa:a8:be:85:6d:75:
        41:89:e9:ae:1d:e4:e1:65:bc:17:f3:b3:a2:ab:45:
        31:eb:9e:21:dc:45:66:0d:8b:2c:70:ea:c2:1d:ac:
        27:9d:0d:d4:06:9c:b0:3d:0b:34:9e:05:2d:9c:55:
        28:f4:63:7f:61:96:da:e7:09:0b:40:b4:d6:0a:5c:
        aa:df
    prime:
        00:bd:70:db:2e:f9:0b:89:37:c4:31:93:48:47:ef:
        d5:ea:7e:bc:da:c8:14:0e:82:dd:f6:c6:07:2a:d4:
        97:c3:02:a1:9b:02:cb:e4:c0:b9:33:d1:bb:69:f0:
        ba:8c:7a:57:1f:df:d3:b5:2f:87:1e:a8:35:e4:c0:
        94:ed:20:04:26:58:50:27:fc:f6:e1:be:c7:b8:7a:
        14:c1:08:16:06:c6:b8:09:dc:34:ea:a0:d1:3e:88:
        bd:b3:bb:05:fe:4d:cb:62:05:9a:c7:00:a2:0b:73:
        ad:dd:39:18:9a:d8:2a:95:ce:f4:10:6a:b2:5c:0f:
        9e:99:e5:e6:0d:6c:19:f5:f5:dc:07:2d:f0:de:b5:
        58:ec:35:33:ef:65:70:c3:8c:bf:14:40:4c:c3:47:
        77:e0:5f:f6:61:5f:49:35:cc:39:75:8e:31:a3:99:
        43:61:d7:e3:b7:b8:0f:79:f3:66:50:95:0d:95:b2:
        5f:1b:2c:9d:64:e0:54:cb:27:e9:4a:23:96:a0:7e:
        55:d4:a9:93:43:b0:69:b2:f5:b4:9d:41:5b:d3:5d:
        4b:91:48:9f:aa:54:a4:a1:81:f1:59:f6:b3:44:8c:
        e7:83:8f:57:63:52:58:70:2f:0a:c1:c0:e5:dd:6f:
        4d:fd:c1:5d:61:6e:d0:a4:bd:15:a1:a6:de:61:c9:
        f4:4b
    generator: 2 (0x2)

prime 是一个大质数,generator 是生成元。

接下来举一个 DH 密钥协商的完整例子。

// 通讯一方生成 DH 参数文件,可以对外公开
$ openssl genpkey -genparam -algorithm DH -out dhp.pem

// 查看参数文件内容,包括 p 和 g 参数
$ openssl pkeyparam -in dhp.pem -text

输出

-----BEGIN DH PARAMETERS-----
MIGHAoGBAO6kIxno65uejqlc0Q+SwnpIQjc9A8DMr1r1xNk9d/qTGczGi52olR96
XfKHZMKCRih4mvFglAfisykwLGdVViiqOQrLmG0uI2WviyPKG4eHqu7gID/6+pil
RBHo6m9McsnlrcGLgV2d3a3IczNcH/g2NnVoKN6Q9+tGiZKhowZDAgEC
-----END DH PARAMETERS-----
DH Parameters: (1024 bit)
    prime:
        00:ee:a4:23:19:e8:eb:9b:9e:8e:a9:5c:d1:0f:92:
        c2:7a:48:42:37:3d:03:c0:cc:af:5a:f5:c4:d9:3d:
        77:fa:93:19:cc:c6:8b:9d:a8:95:1f:7a:5d:f2:87:
        64:c2:82:46:28:78:9a:f1:60:94:07:e2:b3:29:30:
        2c:67:55:56:28:aa:39:0a:cb:98:6d:2e:23:65:af:
        8b:23:ca:1b:87:87:aa:ee:e0:20:3f:fa:fa:98:a5:
        44:11:e8:ea:6f:4c:72:c9:e5:ad:c1:8b:81:5d:9d:
        dd:ad:c8:73:33:5c:1f:f8:36:36:75:68:28:de:90:
        f7:eb:46:89:92:a1:a3:06:43
    generator: 2 (0x2)

发送方 Alice 基于参数文件生成一个密钥对

$ openssl genpkey -paramfile dhp.pem -out akey.pem

// 查看密钥对内容
$ openssl pkey -in akey.pem -text -noout

输出

DH Private-Key: (1024 bit)
    private-key:
        79:1f:07:19:83:8d:34:db:4a:ea:d6:7b:16:4f:7e:
        11:cd:39:78:75:ea:4f:c3:f7:09:48:91:3c:96:cf:
        6b:8d:85:56:48:9e:1a:83:fb:13:0a:28:c5:f6:eb:
        74:13:ff:a4:2e:ae:29:df:b5:92:2a:af:25:11:cf:
        02:b6:09:d5:c8:a1:71:78:86:dd:26:6a:d1:55:52:
        33:ce:65:57:22:3f:f4:df:a6:df:80:c2:cc:c6:98:
        de:67:09:05:e2:68:09:d1:43:7f:42:03:37:99:88:
        cc:5f:78:e6:22:b0:fa:5c:c9:5f:0f:2d:de:b6:33:
        42:05:f4:45:58:b8:fb:93
    public-key:
        4d:90:d3:5f:df:13:fb:17:32:55:6c:3b:17:67:cb:
        51:8f:42:1c:88:10:ef:7b:90:69:2c:e6:97:92:10:
        92:4f:16:8d:d5:9b:4f:d5:97:fa:71:3b:28:12:99:
        1f:86:0d:ee:b2:ca:7e:4f:96:ae:46:73:1d:14:b5:
        0e:1a:0c:e6:41:fa:97:d4:0c:50:a2:17:5d:a9:e8:
        7e:c0:33:fd:dc:59:ca:13:90:f7:1b:79:ee:88:5e:
        39:70:4f:c0:a8:a7:0b:0e:6e:e8:27:29:43:1b:af:
        56:72:0a:aa:a1:06:1d:0d:78:f8:6d:1a:1e:bd:b5:
        3b:20:55:76:bc:9c:1a:d3
    prime:
        00:ee:a4:23:19:e8:eb:9b:9e:8e:a9:5c:d1:0f:92:
        c2:7a:48:42:37:3d:03:c0:cc:af:5a:f5:c4:d9:3d:
        77:fa:93:19:cc:c6:8b:9d:a8:95:1f:7a:5d:f2:87:
        64:c2:82:46:28:78:9a:f1:60:94:07:e2:b3:29:30:
        2c:67:55:56:28:aa:39:0a:cb:98:6d:2e:23:65:af:
        8b:23:ca:1b:87:87:aa:ee:e0:20:3f:fa:fa:98:a5:
        44:11:e8:ea:6f:4c:72:c9:e5:ad:c1:8b:81:5d:9d:
        dd:ad:c8:73:33:5c:1f:f8:36:36:75:68:28:de:90:
        f7:eb:46:89:92:a1:a3:06:43
    generator: 2 (0x2)

接收方 Bob 也基于参数文件生成一个密钥对

$ openssl genpkey -paramfile dhp.pem -out bkey.pem

// 查看密钥对内容
$ openssl pkey -in bkey.pem -text -noout

输出

PKCS#3 DH Private-Key: (1024 bit)
    private-key:
        7b:00:1e:c9:12:62:3a:82:69:58:03:5c:f5:23:ef:
        c2:20:10:27:f5:a7:e3:c9:14:57:76:ea:94:4c:68:
        e5:17:c2:38:36:e1:82:9d:fb:d2:97:04:44:4a:0c:
        9f:81:d3:4a:33:c8:8f:64:50:79:6c:cd:a6:3a:26:
        d0:2b:55:7d:78:b0:e7:1e:12:d8:a3:89:da:61:53:
        1e:d0:9a:9f:f6:c0:ce:7d:c9:25:50:01:cf:c2:cb:
        0d:e2:74:78:3c:58:28:71:38:f0:d3:d2:91:f4:28:
        ec:da:f2:f9:75:e6:c4:13:8c:97:2a:f9:a3:fd:c0:
        0e:cb:d0:17:7d:62:01:c4
    public-key:
        00:8c:ad:e1:2f:42:85:4f:f8:07:7e:15:d0:f9:c5:
        84:b4:a3:be:9d:b2:fb:57:86:b8:c7:0c:d3:d5:92:
        c1:7b:db:e6:e6:b2:7e:ff:db:95:d9:8b:10:1a:10:
        4d:59:ac:b2:00:43:6f:23:f6:aa:13:b6:e4:f4:04:
        92:f1:23:88:13:21:c9:f7:d2:f3:dc:0e:a6:75:20:
        ed:4c:61:29:55:a2:36:55:d3:04:9f:7d:c3:96:7d:
        be:62:44:83:bf:9e:b3:f8:e7:ac:88:c5:3e:9b:b7:
        01:52:63:1a:30:5f:5d:90:46:5b:06:06:f3:b4:f8:
        c4:4b:16:45:43:da:d5:6d:1e
    prime:
        00:ee:a4:23:19:e8:eb:9b:9e:8e:a9:5c:d1:0f:92:
        c2:7a:48:42:37:3d:03:c0:cc:af:5a:f5:c4:d9:3d:
        77:fa:93:19:cc:c6:8b:9d:a8:95:1f:7a:5d:f2:87:
        64:c2:82:46:28:78:9a:f1:60:94:07:e2:b3:29:30:
        2c:67:55:56:28:aa:39:0a:cb:98:6d:2e:23:65:af:
        8b:23:ca:1b:87:87:aa:ee:e0:20:3f:fa:fa:98:a5:
        44:11:e8:ea:6f:4c:72:c9:e5:ad:c1:8b:81:5d:9d:
        dd:ad:c8:73:33:5c:1f:f8:36:36:75:68:28:de:90:
        f7:eb:46:89:92:a1:a3:06:43
    generator: 2 (0x2)

Alice 拆出公钥文件 akey_pub.pem,私钥自己保存

$ openssl pkey -in akey.pem -pubout -out akey_pub.pem

输出

-----BEGIN PUBLIC KEY-----
MIIBHzCBlQYJKoZIhvcNAQMBMIGHAoGBAO6kIxno65uejqlc0Q+SwnpIQjc9A8DM
r1r1xNk9d/qTGczGi52olR96XfKHZMKCRih4mvFglAfisykwLGdVViiqOQrLmG0u
I2WviyPKG4eHqu7gID/6+pilRBHo6m9McsnlrcGLgV2d3a3IczNcH/g2NnVoKN6Q
9+tGiZKhowZDAgECA4GEAAKBgE2Q01/fE/sXMlVsOxdny1GPQhyIEO97kGks5peS
EJJPFo3Vm0/Vl/pxOygSmR+GDe6yyn5Plq5Gcx0UtQ4aDOZB+pfUDFCiF12p6H7A
M/3cWcoTkPcbee6IXjlwT8CopwsObugnKUMbr1ZyCqqhBh0NePhtGh69tTsgVXa8
nBrT
-----END PUBLIC KEY-----

Bob 拆出公钥文件 bkey_pub.pem,私钥自己保存

$ openssl pkey -in bkey.pem -pubout -out bkey_pub.pem

输出

-----BEGIN PUBLIC KEY-----
MIIBIDCBlQYJKoZIhvcNAQMBMIGHAoGBAO6kIxno65uejqlc0Q+SwnpIQjc9A8DM
r1r1xNk9d/qTGczGi52olR96XfKHZMKCRih4mvFglAfisykwLGdVViiqOQrLmG0u
I2WviyPKG4eHqu7gID/6+pilRBHo6m9McsnlrcGLgV2d3a3IczNcH/g2NnVoKN6Q
9+tGiZKhowZDAgECA4GFAAKBgQCMreEvQoVP+Ad+FdD5xYS0o76dsvtXhrjHDNPV
ksF72+bmsn7/25XZixAaEE1ZrLIAQ28j9qoTtuT0BJLxI4gTIcn30vPcDqZ1IO1M
YSlVojZV0wSffcOWfb5iRIO/nrP456yIxT6btwFSYxowX12QRlsGBvO0+MRLFkVD
2tVtHg==
-----END PUBLIC KEY-----

Alice 收到 Bob 他的公钥,并将协商出来的密钥保存到 data_a.txt 中

$ openssl pkeyutl -derive -inkey akey.pem -peerkey bkey_pub.pem -out data_a.txt

输出


b;[nQ?!zX^m��4���Է�M<{|1X?�M3�NT�Łm�Ϧ\��X+<����(L�(�F��l5Yl��N���/o���v�#7���J`>?R�,���!>G������
                                                                                                   ��>B�����$�-��Y
                                                                                                   

对应二进制

$ od -d data_a.txt
                                                                                          0000000     25098   23355   20846   16134    8602   32634   24152   59757
0000020     59416   57652   52209   47060   19942   31548   12668   16216
0000040     19901   56883   21582   50641   28033   53186   23718   55494
0000060     11096   35644   61385   10435   33612   54568   51014   27841
0000100     22837   44908    5587   49486   61576   12198   57967   64511
0000120     60534   56867   14088   38019   19100   15968   16283   57938
0000140     60972   57071   15905     583   49404   47506   61861   47628
0000160      5292   16958   38029   62234   57799   39460   43821   38391
0000200

Bob 收到 Alice 他的公钥,并将协商出来的密钥保存到 data_b.txt 中

$ openssl pkeyutl -derive -inkey bkey.pem -peerkey akey_pub.pem -out data_b.txt

输出


b;[nQ?!zX^m��4���Է�M<{|1X?�M3�NT�Łm�Ϧ\��X+<����(L�(�F��l5Yl��N���/o���v�#7���J`>?R�,���!>G������
                                                                                                   ��>B�����$�-��Y

对应二进制

$ od -d data_b.txt

0000000     25098   23355   20846   16134    8602   32634   24152   59757
0000020     59416   57652   52209   47060   19942   31548   12668   16216
0000040     19901   56883   21582   50641   28033   53186   23718   55494
0000060     11096   35644   61385   10435   33612   54568   51014   27841
0000100     22837   44908    5587   49486   61576   12198   57967   64511
0000120     60534   56867   14088   38019   19100   15968   16283   57938
0000140     60972   57071   15905     583   49404   47506   61861   47628
0000160      5292   16958   38029   62234   57799   39460   43821   38391
0000200

可以发现两者最后协商出来的密钥是完全一致的。

2. ECC 加密

OpenSSL 中支持很多命名的曲线,先来看看支持的曲线有哪些。

$ openssl ecparam -list_curves

输出

  secp112r1 : SECG/WTLS curve over a 112 bit prime field
  secp112r2 : SECG curve over a 112 bit prime field
  secp128r1 : SECG curve over a 128 bit prime field
  secp128r2 : SECG curve over a 128 bit prime field
  secp160k1 : SECG curve over a 160 bit prime field
  secp160r1 : SECG curve over a 160 bit prime field
  secp160r2 : SECG/WTLS curve over a 160 bit prime field
  secp192k1 : SECG curve over a 192 bit prime field
  secp224k1 : SECG curve over a 224 bit prime field
  secp224r1 : NIST/SECG curve over a 224 bit prime field
  secp256k1 : SECG curve over a 256 bit prime field
  secp384r1 : NIST/SECG curve over a 384 bit prime field
  secp521r1 : NIST/SECG curve over a 521 bit prime field
  prime192v1: NIST/X9.62/SECG curve over a 192 bit prime field
  prime192v2: X9.62 curve over a 192 bit prime field
  prime192v3: X9.62 curve over a 192 bit prime field
  prime239v1: X9.62 curve over a 239 bit prime field
  prime239v2: X9.62 curve over a 239 bit prime field
  prime239v3: X9.62 curve over a 239 bit prime field
  prime256v1: X9.62/SECG curve over a 256 bit prime field
  sect113r1 : SECG curve over a 113 bit binary field
  sect113r2 : SECG curve over a 113 bit binary field
  sect131r1 : SECG/WTLS curve over a 131 bit binary field
  sect131r2 : SECG curve over a 131 bit binary field
  sect163k1 : NIST/SECG/WTLS curve over a 163 bit binary field
  sect163r1 : SECG curve over a 163 bit binary field
  sect163r2 : NIST/SECG curve over a 163 bit binary field
  sect193r1 : SECG curve over a 193 bit binary field
  sect193r2 : SECG curve over a 193 bit binary field
  sect233k1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect239k1 : SECG curve over a 239 bit binary field
  sect283k1 : NIST/SECG curve over a 283 bit binary field
  sect283r1 : NIST/SECG curve over a 283 bit binary field
  sect409k1 : NIST/SECG curve over a 409 bit binary field
  sect409r1 : NIST/SECG curve over a 409 bit binary field
  sect571k1 : NIST/SECG curve over a 571 bit binary field
  sect571r1 : NIST/SECG curve over a 571 bit binary field
  c2pnb163v1: X9.62 curve over a 163 bit binary field
  c2pnb163v2: X9.62 curve over a 163 bit binary field
  c2pnb163v3: X9.62 curve over a 163 bit binary field
  c2pnb176v1: X9.62 curve over a 176 bit binary field
  c2tnb191v1: X9.62 curve over a 191 bit binary field
  c2tnb191v2: X9.62 curve over a 191 bit binary field
  c2tnb191v3: X9.62 curve over a 191 bit binary field
  c2pnb208w1: X9.62 curve over a 208 bit binary field
  c2tnb239v1: X9.62 curve over a 239 bit binary field
  c2tnb239v2: X9.62 curve over a 239 bit binary field
  c2tnb239v3: X9.62 curve over a 239 bit binary field
  c2pnb272w1: X9.62 curve over a 272 bit binary field
  c2pnb304w1: X9.62 curve over a 304 bit binary field
  c2tnb359v1: X9.62 curve over a 359 bit binary field
  c2pnb368w1: X9.62 curve over a 368 bit binary field
  c2tnb431r1: X9.62 curve over a 431 bit binary field
  wap-wsg-idm-ecid-wtls1: WTLS curve over a 113 bit binary field
  wap-wsg-idm-ecid-wtls3: NIST/SECG/WTLS curve over a 163 bit binary field
  wap-wsg-idm-ecid-wtls4: SECG curve over a 113 bit binary field
  wap-wsg-idm-ecid-wtls5: X9.62 curve over a 163 bit binary field
  wap-wsg-idm-ecid-wtls6: SECG/WTLS curve over a 112 bit prime field
  wap-wsg-idm-ecid-wtls7: SECG/WTLS curve over a 160 bit prime field
  wap-wsg-idm-ecid-wtls8: WTLS curve over a 112 bit prime field
  wap-wsg-idm-ecid-wtls9: WTLS curve over a 160 bit prime field
  wap-wsg-idm-ecid-wtls10: NIST/SECG/WTLS curve over a 233 bit binary field
  wap-wsg-idm-ecid-wtls11: NIST/SECG/WTLS curve over a 233 bit binary field
  wap-wsg-idm-ecid-wtls12: WTLS curve over a 224 bit prime field
  Oakley-EC2N-3:
	IPSec/IKE/Oakley curve #3 over a 155 bit binary field.
	Not suitable for ECDSA.
	Questionable extension field!
  Oakley-EC2N-4:
	IPSec/IKE/Oakley curve #4 over a 185 bit binary field.
	Not suitable for ECDSA.
	Questionable extension field!
  brainpoolP160r1: RFC 5639 curve over a 160 bit prime field
  brainpoolP160t1: RFC 5639 curve over a 160 bit prime field
  brainpoolP192r1: RFC 5639 curve over a 192 bit prime field
  brainpoolP192t1: RFC 5639 curve over a 192 bit prime field
  brainpoolP224r1: RFC 5639 curve over a 224 bit prime field
  brainpoolP224t1: RFC 5639 curve over a 224 bit prime field
  brainpoolP256r1: RFC 5639 curve over a 256 bit prime field
  brainpoolP256t1: RFC 5639 curve over a 256 bit prime field
  brainpoolP320r1: RFC 5639 curve over a 320 bit prime field
  brainpoolP320t1: RFC 5639 curve over a 320 bit prime field
  brainpoolP384r1: RFC 5639 curve over a 384 bit prime field
  brainpoolP384t1: RFC 5639 curve over a 384 bit prime field
  brainpoolP512r1: RFC 5639 curve over a 512 bit prime field
  brainpoolP512t1: RFC 5639 curve over a 512 bit prime field
  SM2       : SM2 curve over a 256 bit prime field

生成一个参数文件,通过 -name 指定命名曲线

$ openssl ecparam -name secp256k1 -out secp256k1.pem

// 查看参数文件,下面这句话默认只打印曲线名字
$ openssl ecparam -in secp256k1.pem -text -noout

输出

ASN1 OID: secp256k1

-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----

显示参数文件内具体参数

// 显示参数文件内具体参数
$ openssl ecparam -in secp256k1.pem -text -param_enc explicit -noout

输出

Field Type: prime-field
Prime:
    00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:fe:ff:
    ff:fc:2f
A:    0
B:    7 (0x7)
Generator (uncompressed):
    04:79:be:66:7e:f9:dc:bb:ac:55:a0:62:95:ce:87:
    0b:07:02:9b:fc:db:2d:ce:28:d9:59:f2:81:5b:16:
    f8:17:98:48:3a:da:77:26:a3:c4:65:5d:a4:fb:fc:
    0e:11:08:a8:fd:17:b4:48:a6:85:54:19:9c:47:d0:
    8f:fb:10:d4:b8
Order:
    00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:
    ff:fe:ba:ae:dc:e6:af:48:a0:3b:bf:d2:5e:8c:d0:
    36:41:41
Cofactor:  1 (0x1)

参数解释:

  • A 和 B 是椭圆曲线公式参数
  • P 大质数,它把 ECC 所有点的大小都控制在有限域中。几乎所有的 ECC 操作都会对 P 进行取模运算
  • Generator 就是基点 G。由 (gx,gy) 组合
  • Order 相当于基点的 n。也就是基点的打点次数。大部分的 ECC 操作都不需要这个值,除了 ECDSA 在计算签名的时候会对 Order 取模,而不是对 P 取模
  • Cofactor 该值等于椭圆曲线上所有点总数除以 n。

在 ECC 中,k 就是私钥,g 就是基点,kg 基于公式运算最终得到公钥,通过公钥很难计算出私钥 k,其背后有复杂的数学理论,即离散对数问题。

接下来举一个 ECDH 密钥协商的完整例子。

// 生成参数文件
$ openssl ecparam -name secp256k1 -out secp256k1.pem

输出

-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----

Alice 生成 EDCH 私钥对文件

$ openssl genpkey -paramfile secp256k1.pem -out akey.pem

输出

-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgXVTzOp6aEkAeC2ICiPTi
bmAZkr1RYtzprh3Larg4n/yhRANCAATbDBxnW/pTc6fS1Rk/bJEZZLp0fBGfn+H8
hYJILjrQu7ZORRlQqe+o2le1+OV2t/l3bEGOYAI8nvHOhT6weN/e
-----END PRIVATE KEY-----

Bob 生成 EDCH 私钥对文件

$ openssl genpkey -paramfile secp256k1.pem -out bkey.pem

输出

-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgjhUWgm7C3tcXTUcqX9RG
aHCJQ5BqF0OzCBYntGnhJwahRANCAARPI4E54N3VfbHTfcvoUXNGJrIcMHAEhj6t
TkKrpEYMCbPkM0g57C2DWcOIqvb9ImD8OYQ+N27LlVNhYt6ncD/v
-----END PRIVATE KEY-----

Alice 分解出公钥,将公钥发送给 Bob

$ openssl pkey -in akey.pem -pubout -out akey_pub.pem

输出

-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2wwcZ1v6U3On0tUZP2yRGWS6dHwRn5/h
/IWCSC460Lu2TkUZUKnvqNpXtfjldrf5d2xBjmACPJ7xzoU+sHjf3g==
-----END PUBLIC KEY-----

Bob 分解出公钥,将公钥发送给 Alice

$ openssl pkey -in bkey.pem -pubout -out bkey_pub.pem

输出

-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyOBOeDd1X2x033L6FFzRiayHDBwBIY+
rU5Cq6RGDAmz5DNIOewtg1nDiKr2/SJg/DmEPjduy5VTYWLep3A/7w==
-----END PUBLIC KEY-----

Alice 收到 Bob 他的公钥,并将协商出来的密钥保存到 data_a.txt 中

$ openssl pkeyutl -derive -inkey akey.pem -peerkey bkey_pub.pem -out data_a.txt

输出

��tR�"��g����_������]�Vn�Uɺ

对应二进制

$ od -d data_a.txt

0000000     38303   21108    8888   49924   26595   54407   63697   57439
0000020     61643   63942   37357   63837   28246    3817    5973   47817
0000040

Bob 收到 Alice 他的公钥,并将协商出来的密钥保存到 data_b.txt 中

$ openssl pkeyutl -derive -inkey bkey.pem -peerkey akey_pub.pem -out data_b.txt

输出

��tR�"��g����_������]�Vn�Uɺ

对应二进制

$ od -d data_a.txt

0000000     38303   21108    8888   49924   26595   54407   63697   57439
0000020     61643   63942   37357   63837   28246    3817    5973   47817
0000040

可以发现两者最后协商出来的密钥是完全一致的

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

物联网安全系列 - 非对称加密算法 ECDH 的相关文章

  • ROS环境下串口通信

    1 环境 xff1a 操作系统 Ubuntu 14 04ROS版本 ROS Indigo 2 步骤 xff1a 2 1 下载安装ROS对应版本的工具包 此处为indigo版 输入以下命令安装 xff1a sudo apt span clas
  • docker的迁移备份

    在工作中 xff0c 有时候可能需要把正在运行的容器 xff0c 迁移到另外一台服务器上 或者需要把某个容器备份 本文档记录docker如何迁移和备份容器 容器保存为镜像 下面是我虚拟机中正在运行的容器 以mynginx容器为例 xff0c
  • 技术面试(一)认识技术面试

    面试这件事听起来似乎挺简单 xff0c 做起来却非常困难 不妨先听听面试官的真实 吐槽 xff1a 是不是拿算法题让候选人做就好了 xff1f 可如果他做过这个题目怎么办 xff1f 候选人都是工作好多年的老司机了 xff0c 怎么有面试官
  • Pix4飞控硬件平台框架(一)

    硬件平台简介 本文只是为了让大家简单入门为主 xff0c 所以我选择的硬件学习平台是Pixhawk系列的mRoPixhawk xff0c 兼容原始版本Pixhawk1 xff0c 基于Pixhawk project FMUv3开源硬件设计
  • Pix4飞控常见问题解决方法(二)

    一 无法解锁 xff08 黄灯闪烁 xff09 无法解锁的原因会有多种 xff0c 请按照如下步骤进行检查 xff1a 1 初始设置是否全部完成 a 机架类型选择是否正确 xff0c 或者你根本就没有选择 xff1f 注意 xff0c 新版
  • 基于libuvc的相机配置说明

    很多相机支持uvc 1 的传输格式 ros官网自带的libuvc xff0c 支持uvc格式的视频流 xff0c 本文主要对这个链接中的一些细节 xff0c 进行补充说明 step 1 插入usb step 2 获取基本信息 查找camer
  • Ehcache依赖版本问题:Another CacheManager with same name 'es' already exists in the same VM.

    最近在写一个shiro 的demo用到Ehcache缓存配置 结果在启动项目的时候出错 span style font size 14px Caused by net sf ehcache CacheException Another Ca
  • ubuntu 创建新用户并添加到docker组

    useradd myuser passwd myuser first create the directory mkdir p home myuser usermod s bin bash d home myuser myuser cp r
  • SM2 签名前要进行的预处理操作

    一般情况下 xff0c 计算数字签名时应执行以下操作 xff1a 1 计算原始数据的 Hash 值 xff1b 2 将 Hash 值作为输入 xff0c 计算签名函数的输出 并不是对原始数据直接签名 xff0c 而是对 Hash 值签名 验
  • VR行业的发展现状和前景

    5G技术的应用推广 xff0c 加速推动虚拟现实不断发展和完善 xff0c VR产业迅速在各个领域和行业都得到广泛应用 xff0c 最好直观的感受就是知觉体验得到了良好的增强作用 本文的主要内容是简单概括VR技术的发展现状和发展前景 一 V
  • Intel真情告白:我的眼里只有你 –UP Squared Board

    近期 xff0c 物联网领域最大的喜讯莫过于研扬科技携手Intel 共同推出一款 UP SQUARED GROVE 物联网开发套件 对于这次喜结良缘 xff0c Intel 官网也是不加修饰的大方昭告天下 xff1a 我的眼里只有你 xff
  • 【问题与方法】联想拯救者双系统重启卡死机解决方案

    码字不易 xff0c 如果各位看官感觉该文章对你有所帮助 xff0c 麻烦点个关注 xff0c 如果有任何问题 xff0c 请留言交流 如需转载 xff0c 请注明出处 xff0c 谢谢 文章链接 xff1a 问题与方法 联想拯救者双系统重
  • 【深度学习】训练集、测试集和验证集

    码字不易 xff0c 如果各位看官感觉该文章对你有所帮助 xff0c 麻烦点个关注 xff0c 如果有任何问题 xff0c 请留言交流 如需转载 xff0c 请注明出处 xff0c 谢谢 文章链接 xff1a https blog csdn
  • 【深度学习】ubuntu系统指定gcc版本并调整优先级

    sudo apt install build essential gcc version xff08 查看gcc版本 xff09 可以看到我的gcc版本是4 8 5 安装最新版gcc9 sudo apt install software p
  • 【深度学习】Ubuntu增加Swap交换空间大小

    前言 xff1a 做Ubuntu系统时 xff0c 选择了默认空间分配方案 xff0c Swap空间仅2G xff0c 而你的内存有16G xff0c 分给Swap空间至少为内存的1倍 xff0c 最好是内存值的2倍 xff0c 系统相当卡
  • 【论文阅读】Anchor3DLane: Learning to Regress 3D Anchors for Monocular 3D LaneDetection

    Anchor3DLane 针对单目的3D车道线检测去学习回归3D锚 摘要 xff1a 单目的3D车道线检测是一个非常具有挑战性的问题 xff0c 因为他缺少深度的信息 xff0c 3D车道线检测一个非常流行的方法是将前视图转换成鸟瞰图 xf
  • 【深度学习】训练模型结果同时显示,模型结果对比

    码字不易 xff0c 如果各位看官感觉该文章对你有所帮助 xff0c 麻烦点个关注 xff0c 如果有任何问题 xff0c 请留言交流 如需转载 xff0c 请注明出处 xff0c 谢谢 文章链接 xff1a 深度学习 训练模型结果同时显示
  • 【问题与方法】如何使用vscode配置远程git仓库

    码字不易 xff0c 如果各位看官感觉该文章对你有所帮助 xff0c 麻烦点个关注 xff0c 如果有任何问题 xff0c 请留言交流 如需转载 xff0c 请注明出处 xff0c 谢谢 配置git xff0c 看我这一篇其实就够了 问题与
  • 【车道线算法】GANet-车道线检测环境配置一文通关

    目录 GANet配置全纪录 下载代码 conda环境部署 安装torch和cudatoolkit 安装其他包 编译 总结 GANet配置全纪录 下载代码 GitHub Wolfwjs GANet A Keypoint based Globa
  • 【雷达】如何将三维点云映射到二维平面

    最近在做基于雷达点云的交通标识牌识别时 xff0c 需要按照HAD格式进行输出 xff0c 由于交通标识牌不一定会与坐标轴垂直 xff0c 那么如何找到矩形标识牌的四个顶点 xff0c 是待解决的问题 由于标识牌一定是平面的 xff0c 三

随机推荐

  • ceres 拟合曲线

    假设有一条满足以下方程的曲线 xff1a 其中a b c为曲线的参数 xff0c w为高斯噪声 这是一个非线性模型 假设我们有N个关于x y的观测数据点 xff0c 想根据这些数据点求出曲线的参数 那么 xff0c 可以求解下面的最小二乘问
  • 独家!了不起的UP系列产品,不一样的开发板—UP Board(一)

    AAEON自2016年推出第一代UP board问世以来 xff0c 其信用卡大小的苗条小身材 xff08 世界首创Intel平台信用卡大小开发板 xff09 xff0c 配备上Intel Atom x5 z8350 处理器 xff0c 兼
  • 追求技术之路 - 那些陪伴我的书籍

    如今已经在广州一家嵌入式公司实习 xff0c 分享大学里度过的一些书籍 xff0c 有些还没读完 xff0c 个人比较喜欢经典书籍 xff0c 研读起来就有种奇妙的感觉 xff0c 比起人与人之间的复杂的关系 xff0c 书籍带给我的感觉很
  • 编程之美 -- 中国象棋将帅问题

    下过中国象棋的朋友都知道 xff0c 双方的 将 和 帅 相隔遥远 xff0c 并且它们不能照面 在象棋残局中 xff0c 许多高手能利用这一规则走出精妙的杀招 假设棋盘上只有 将 和 帅 二子 xff08 为了下面叙述方便 xff0c 我
  • C++单元测试工具 -- CppUnit

    CppUnit 作为C 43 43 语言的一款测试工具 xff0c 其实也是一个开源项目 xff0c 与JUnit一样 xff0c 用来方便开发人员进行单元测试的工具 项目地址 xff1a http sourceforge net apps
  • 拒绝游戏!发愤图强!

    立帖为证 xff01 xff01 xff01
  • C++ STL — 第6章 STL容器(二)deque

    C 43 43 STL容器deque和vector很类似 xff0c 也是采用动态数组来管理元素 使用deque之前需包含头文件 xff1a include lt deque gt 它是定义在命名空间std内的一个class templat
  • C++ STL — 第6章 STL容器(三)list

    一 list基础 List使用一个双向链表来管理元素 图一显示了list的结构 图一 list的结构 任何型别只要具备赋值和可拷贝两种性质 xff0c 就可以作为list的元素 二 list的功能 list的内部结构和vector和dequ
  • STL list remove和sort函数

    include lt iostream gt include lt list gt include lt iterator gt using namespace std bool cmp int a int b return a gt b
  • 排序 -- 简单选择排序

    选择排序 思想 xff1a 每一趟 n i 43 1 xff08 i 61 1 2 3 n 1 xff09 个记录中选择关键字最小的记录作为有序序列的第i个记录 简单选择排序 xff1a 通过n i次关键字间的比较 xff0c 从n i 4
  • HDOJ 1106 排序

    题目地址 xff1a http acm hdu edu cn showproblem php pid 61 1106 Problem xff1a 输入一行数字 xff0c 如果我们把这行数字中的 5 都看成空格 xff0c 那么就得到一行用
  • Jetson Xavier、Jetson TX2、 1080(Ti)、2080显卡运行深度学习模型性能对比(英伟达开发平台VS常用显卡)

    前言 xff1a 英伟达的Jetson TX2使得很多人认为深度学习模型终于可以像嵌入式开发平台那样做到小型化了 xff0c 不用再跑在高配计算机或者服务器上面了 xff0c 但是实际上Jetson TX2开发板的性能和深度学习常用到的10
  • 独家!了不起的UP系列产品,不一样的开发板 — UP Squared Board(二)

    UP 系列家族的成员 xff0c 经过团队经年累月的精心研发 xff0c 产品已不断丰富起来 先后开发出了第二代产品UP Squared 与第一代产品UP Board相比 xff0c 拥有 高性能低功耗的 UP Squared 似乎更令人兴
  • STM32连接--OneNET,阿里云(MQTT协议)详细教程

    x1f495 对于物联网工程 xff0c 不可或缺的必然是连接上云 xff0c 今天本人总结了上云经验 xff0c 希望对大家起到帮助哦 有用的话记得点赞收藏哦 关于如何连接OneNET OneNET https open iot 1008
  • HTTP Digest接入方式鉴权认证流程

    HTTP Digest接入方式鉴权认证流程 一 摘要认证原理 摘要认证与基础认证的工作原理很相似 xff0c 用户先发出一个没有认证证书的请求 xff0c Web服务器回复一个带有WWW Authenticate头的响应 xff0c 指明访
  • 6.2随笔

    今天打牛客 xff0c 用python写了一题 xff0c 结果发现用空格隔开的两个数不知道怎么输入 代码 xff1a n span class token punctuation span m span class token opera
  • 蓝牙Mesh简介

    蓝牙mesh简介 蓝牙Mesh的基本概念 蓝牙Mesh是2017年7月蓝牙技术联盟 xff08 Bluetooth SIG xff09 正式推出的蓝牙设备组网标准 我们知道蓝牙ble设备可以与其他设备建立GATT连接 xff0c 然后进行
  • 蓝牙Mesh的基本概念

    蓝牙mesh简介 蓝牙Mesh的基本概念 蓝牙Mesh是基于ble广播进行消息传递的一种蓝牙组网通讯网络 xff0c 是一种采用网络洪泛的方式无中心 无路由的对等网络 以实现蓝牙设备与蓝牙设备之间的多对多通讯 xff0c 使蓝牙在物联网智能
  • JLink Commander调试方法

    JLink Commander调试方法 1 背景 目前开发中常用的调试手段主要有串口 IO口输出作为调试方式 目前串口的限制较多 xff0c 有些硬件不太方便接串口或者一些实时的数据 xff0c 当时没有接串口则无法实时获取调试信息 IO调
  • 物联网安全系列 - 非对称加密算法 ECDH

    非对称加密算法 ECDH 背景 之前的章节讲到了对称加密算法AES xff0c 发送方和接收方需要使用相同的密钥进行通讯 xff0c 但是发送方怎么将密钥安全的发送给接收方 xff1f 这是一个问题 密钥分配问题 对称加密算法中 xff0c