openssl-key-exchange

本文摘自我在GitHub的开源项目 https://github.com/zhoupeng6d/openssl-key-exchange


简介

该方案介绍一种通过ECDH椭圆曲线算法进行密钥交换的流程和方法,这种方案可以在的不安全的通信场景下进行AES密钥协商,即使有第三者监听到了所有的密钥交换信息,也无法获知最终计算出的AES密钥,防止MITM(Man-in-the-middle attack 中间人攻击)。

这种方案可典型的应用于蓝牙BLE Peripheral 跟 Central 间的密钥协商,但是本文更多的聚焦在密钥交换流程和原理上,而非具体的应用场景,所以只是抽象成了Client和Server两种角色。

Client和Server之间通过[rpclib]进行通信,Server提供了某些服务,可被Client进行远程访问。

一个Server至少提供两个服务,一个是密钥交换服务,另一个是加密后的数据通信服务。在这个项目中,我们的 Server 通过 rpclib 绑定了两个服务:

1. "key_exchange_request", Client访问该服务完成密钥交换;

2. "encrypted_request", Client在密钥交换完成后使用加密过的数据访问该服务。

Server和Client之间传输的消息使用protobuf,协议定义参考[key_exchange.proto]

构建&运行

目前已经在Ubuntu和MacOS上做了验证,需要主机安装openssl库和protobuf3.0+库

安装libssl库:

$ sudo apt-get install libssl-dev

安装protobuf3.0+,请参考[https://github.com/protocolbuffers/protobuf/blob/master/src/README.md]

安装完libssl和protobuf后:

$ git clone https://github.com/zhoupeng6d/openssl-key-exchange.git$ cd openssl-key-exchange$ git submodule init$ git submodule update$ mkdir build$ cmake ..$ make$ ./server$ ./client # run the client in another terminal window

目录结构

.├── CMakeLists.txt // cmake 构建文件├── LICENSE // 项目开源许可├── README.md // 程序说明├── README_CN.md // 程序说明中文版├── README_EN.md // 程序说明英文版├── deps // 依赖的第三方库目录├── protos│ └── key_exchange.proto // 协议定义文件├── readme_images└── src├── client.cc // Client 主程序源码├── common.h // 公共函数头文件源码├── crypto.cc // 基于openssl封装的密钥交换和加解密函数包├── crypto.h // 加解密函数包头文件├── hex_dump.h // 二进制dump└── server.cc // Server 主程序源码

项目中用到的算法标准:

1. ECDH (Elliptic-Curve Diffie–Hellman NIST P-256)

2. HKDF (HMAC-based Extract-and-Expand Key Derivation Function Refer to RFC 5869)

3. HMAC (Hash-based Message Authentication Code SHA-256)

4. AES (AES-256-GCM)

流程图

该流程包含两个主要的阶段

1. Key Exchange阶段,密钥交换,最终协商出一个AES对称密钥;

2. Encrypted Communication阶段,使用上一步协商出的密钥进行AES加密通信。

Key Exchange阶段

1. KEY_EXCHANGE_INITIATE Request,Client将自己的ECDH公钥(65字节)和Salt(32字节随机数)发送给Server;

2. KEY_EXCHANGE_INITIATE Response,Server将自己的ECDH公钥(65字节)和Salt(32字节随机数)发送给Client;

3. Key Calculation,Client端收到Server端在上一步发过来的消息后,使用key_calculate()函数计算AES密钥(32字节);

4. KEY_EXCHANGE_FINALIZE Request,当Client正确的计算出了AES密钥,发送该消息通知Server完成密钥交换;

5. Key Calculation,Server端收到Client端在上一步发过来的消息后,同样适用key_calculate()函数计算AES密钥;

6. KEY_EXCHANGE_FINALIZE Response,Server端的密钥计算完成后,回复OK给Client端,这样就完成了整个密钥交换流程。

key_calculate()函数计算步骤

1. 将自己的Salt和对方的Salt进行XOR运算,生成一个XorSalt(32字节);

2. 使用自己的ECDH公钥+私钥,以及对方的ECDH公钥,通过ECDH算法计算出一个共享密钥SharedKey(32字节);

3. 使用第一步的XorSalt和第二步的SharedKey,并使用固定的字符串"ENCRYPTION"作为Info输入,使用HKDF算法计算出最终的AES密钥。

Encrypted Communication阶段

1. Token生成,每次通信时生成一个3字节的随机数,用这个随机数和自己的ECDH公钥,使用HMAC算法计算出一个哈希值,我们称之为Token。

2. 将上一步的随机数和Token插入Encrypted Request中,以及加密后的Ciphertext一并发给Server;

3. Server收到Encrypted Request后,根据保存的密钥交换过的设备公钥和Client发过来的随机数,计算出一个Token,如果跟Client发过来的Token一致,那就认为该设备是一个受信设备,并解密接下来的Ciphertext。

设备合法性校验(本项目不做实现)

如果你理解了上面的密钥交换流程,那么你肯定发现了一个问题,就是任何Client都可以用同样的一套机制跟Server进行通信,显然我们的目的不是实现一种[隐蔽式安全](http://www.ituring.com.cn/book/miniarticle/129179)算法。

要实现设备的合法性校验,就要将双方的公钥提前录入到对方设备中,或者将公钥录入到一个双方都能访问的鉴权服务器中。需要提前录入的信息可以通过计算设备公钥的哈希来实现。

根据上面的流程图,我们可以在步骤1(Server收到Client的KEY_EXCHANGE_INITIATE Request)和步骤2(Client收到Server的KEY_EXCHANGE_INITIATE Response)后面分别加入公钥验证流程,这样Client和Server就可以相互验证对方的身份,如果对方的身份跟预留信息不相符,那就拒绝他的密钥交换请求。

蓝牙配对应用

如果要把这套机制应用在蓝牙主从设备之间,一般是由蓝牙从设备来提供相应的服务供主机访问,那么,蓝牙从设备作为Server角色,蓝牙主设备作为Client角色。

从设备至少提供两个Service UUID,一个负责密钥交换服务,另一个负责数据加密通信。

为了实现Request和Response,每个Service UUID下面至少实现两个通道,一个用来接收Request(write属性),一个用来发送Response(Notify属性),一个典型的Profile例子如下:

├──UUID 0xFF10 // Primary Service -- Key Exchange│ ├── UUID 0xFFF1 // Write Characteristic│ └── UUID 0xFFF2 // Notify Characteristic│└──UUID 0xFF20 // Primary Service -- Encrypted Communication├── UUID 0xFFF1 // Write Characteristic└── UUID 0xFFF2 // Notify Characteristic

在本工程的代码中,Client在经过了 KeyExchange 之后会在每一次的 EncryptedRequest 中加入一个 Token,以用来标识自己的身份。但如果是蓝牙设备,Token 由从设备(Server)来生成,Token可以放在从设备广播包的 manufacturer 字段中,这样的话,无需建立连接,就可以判断设备是否经过了密钥交换。

0 Flag(0xFF)
1 Length
2-4 Salt
5-7 HMAC

鸣谢

本项目基于以下非常优秀的项目构建,排名无先后:

  • [rpclib]
  • [openssl]
  • [protobuf]

openssl-key-exchange 基于ECDH (Elliptic-Curve Diffie–Hellman) 的密钥交换流程相关推荐

  1. Elliptic curve Diffie–Hellman

    原文地址:https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman Elliptic curve Diffie–Hellm ...

  2. Unable to negotiate with x.x.x.x port 22: no matching key exchange method found. Their offer: diffie

    今天需要ssh到centos5.10 64位机器上做点事情. windows和linux上 都运行ssh-keygen,一路回车,分别在两个系统的用户目录下生成.ssh文件夹 把windows .ss ...

  3. ECDH秘钥协商算法原理(ECDH Key Exchange)

    ECDH全称是椭圆曲线迪菲-赫尔曼秘钥交换(Elliptic Curve Diffie–Hellman key Exchange),主要是用来在一个不安全的通道中建立起安全的共有加密资料,一般来说交换 ...

  4. ECDH 密钥交换举例(ECDH Key Exchange - Examples)

    现在,让我们用Python实现ECDH算法(Elliptic Curve Diffie–Hellman Key Exchange). 我们将使用Python中用于ECC的tinyec库: pip in ...

  5. Diffie–Hellman key exchange

    原文地址:https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange Diffie–Hellman key exchange F ...

  6. Diffie Hellman密钥交换

    In short, the Diffie Hellman is a widely used technique for securely sending a symmetric encryption ...

  7. 隐私计算加密技术基础系列-Diffie–Hellman key exchange

    1 密码学 1.1 背景 隐私计算(Privacy-preserving computation)是指在保证数据提供方不泄露原始数据的前提下,对数据进行分析计算的一系列信息技术,保障数据在流通与融合过 ...

  8. Elliptic Curve Cryptography: 轻轻的学

    Elliptic Curve Cryptography: 轻轻的学 Elliptic curves Algebraic addition Scalar multiplication Multiplic ...

  9. linux安装Openssl步骤详解_问题:OpenSSL: error:100AE081:elliptic curve routines:EC_GROUP_new_by_curve_name:un

    linux上安装Openssl步骤详解 问题: OpenSSL: error:100AE081:elliptic curve routines:EC_GROUP_new_by_curve_name:u ...

最新文章

  1. linux mysql主主复制_MySQL主从复制与主主复制
  2. mysql 免安装版配置方法(经测试可行)
  3. 05 Python - Python运行
  4. junit5 动态测试_JUnit 5 –动态测试
  5. ubuntu14.04配置caffe
  6. 华为Mate 20 X 5G版本月起全球开卖:国内上市的首款5G手机
  7. 编程范式之rotate操作
  8. 为什么考研的都不是班里最优秀的?
  9. java反编译之 基础篇(class未加密未混淆)
  10. python的zip_python中的zip()函数
  11. java interface 传值_前后端分离传值方案-RestfulAPI
  12. matlab 暴雨强度公式,利用MATLAB推导城市暴雨强度公式
  13. 明解c语言第7章答案,明解C语言 入门篇 第六章答案
  14. 最值得收藏的Bootstrap免费字体和图标网站
  15. Vue指令之条件渲染
  16. 极具挑战性的工作:升级模式库从CQ2002到CQ7
  17. python--if语句判断数字正负值
  18. 图像直方图均衡化和空间滤波
  19. 慕课matlab学习 第四章-021窗口分割、标注、和坐标控制
  20. org.hibernate.ObjectNotFoundException

热门文章

  1. (转)视觉工程师笔试知识汇总
  2. 机器视觉工程师的几种类型
  3. 实验一 linux常用命令
  4. 与Java相关的四十个名字,
  5. 乐字节炫酷HTML 与 CSS
  6. 毕业季——在校生讲述
  7. 【经验】为什么Android手机连接USB后查看手机内部图片有些有缩略图,有些显示图标?
  8. 用python输出沙漏_sandglass(沙漏)——一个让人解脱的python时间处理库
  9. 你也遇到JSONException:create instance error, null...问题啦?
  10. 白噪声检验python_python 加一个白噪声跟老齐学Python之Python安装