主要内容:本文主要介绍使用uECC加速mbedTLS ecdh和ecdsa流程的方法。
mbedtls是被广泛使用的开源安全加密库,在实际使用过程中发现,ecdh和ecdsa的软件计算过程耗时比较长。
针对这一情况,常常使用uecc代替mbedtls的部分实现,来达到加速的效果。但如果应用希望保留使用mbedtls的接口,又要如何通过uecc加速呢?答案是对mbedtls的参数和uecc的参数进行转换,在内部替换掉mbedtls的部分实现。
1 uECC加速
1.1 ecdh-生成公开参数
ecdh生成公开参数的函数是 mbedtls_ecdh_gen_public()
,实际测试过程中发现该函数比较耗时。
它的输出的结果保存在 d
和 Q
这两个参数中。因此我们使用 uECC_make_key()
产生公私钥对之后,再转换成对应的格式即可。
1 |
|
1.2 ecdh-生成共享密钥
mbedtls_ecdh_compute_shared()
生成共享密钥的时候,输入参数是Q
和d
,生成的共享密钥输出到z
。因此我们先从Q
得到uECC所需要的pubKey
,从d
得到uECC所需要的priKey
;然后使用uECC_shared_secret()
得到sharedKey之后再转换成mbedtls所需要的z
即可。
1 | int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, |
1.3 ecdsa-校验签名
ecdsa校验签名的过程中,发现是 ecdsa_verify_restartable()
这个方法比较耗时。我们需要使用uECC_verify()
来代替 ``ecdsa_verify_restartable()`验签函数。
- 根据
&ctx->Q
和曲线参数转换成pub_key_buf
- 将mbedtls签名转换成uECC的签名格式
- 使用
uECC_verify()
验证签名
1 |
|
其中,mbedtls_ecdsa_get_uecc_sig()
是将mbedtls的asn1格式的签名数据,转换成uECC的 r+s
的签名格式:
1 | /** |
2 uECC加速实战
2.1 ecdh加速实验
2.1.1 ECDH共享参数
双方在进行ECDH密钥协商之前,需要选择相同的椭圆曲线方程、大素数p和生成元G。
(1)选择相同的大素数p;
(2)选择椭圆曲线方程E:y^2 = x^3+ax+b mod p
(3)选择相同的生成元G(Gx, Gy)。
在实际应用中,如果约定使用标准曲线如 secp256r1,那么双方就可以很容易地确认大素数P、椭圆曲线方程和生成元。
2.1.2 密钥协商过程
(1)Alice选择一个比椭圆曲线的阶小的随机数da作为私密参数,该参数可以理解为Alice的私钥,计算Qa = daG = (xa, ya),并把Qa发给Bob
(2)Bob选择一个比椭圆曲线的阶小的随机数db作为私密参数,该参数可以理解为Bob的私钥,计算Qb = dbG = (xb, yb),并把Qb发给Alice
(3)Bob收到Qa后计算得到共享密钥Kb = dbQa = db(daG)
(4)Alice收到Qb后计算得到共享密钥Ka = daQb = da(dbG)
根据椭圆结合律,db(daG) = da(dbG) = (xq, yq)。即得到相同的共享密钥 Kb = Ka。实际使用可以是xq和yq两部分,也可以是xq单一部分。
2.1.3 实验对比
测试代码:
1 | int main( int argc, char *argv[] ) |
ecdh的实验结果如下:
1 | ecdh 18.827000 seconds without uecc. |
2.2 ecdsa加速实验
测试代码:
1 | int main( int argc, char *argv[] ) |
ecdsa的对比结果如下:
1 | ecdsa 21.767000 seconds without uecc. |
这是在windows平台上测试的结果。实际在MCU平台上测试的结果是接近10倍的优化。
参考资料:
- https://github.com/kmackay/micro-ecc (static版本)