1. ZMQ 官方文档

ZMQ 的官方文档中关于 curve 的介绍如下:

Client and server roles

A socket using CURVE can be either client or server, at any moment, but not both. The role is independent of bind/connect direction.

A socket can change roles at any point by setting new options. The role affects all zmq_connect and zmq_bind calls that follow it.

To become a CURVE server, the application sets the ZMQ_CURVE_SERVER option on the socket, and then sets the ZMQ_CURVE_SECRETKEY option to provide the socket with its long-term secret key. The application does not provide the socket with its long-term public key, which is used only by clients.

To become a CURVE client, the application sets the ZMQ_CURVE_SERVERKEY option with the long-term public key of the server it intends to connect to, or accept connections from, next. The application then sets the ZMQ_CURVE_PUBLICKEY and ZMQ_CURVE_SECRETKEY options with its client long-term key pair.

If the server does authentication it will be based on the client's long term public key.

  

官方文档中提到的几个点都很关键:

  • 一个 curve socket 既可以是服务端,也可以是客户端。但不可以既是服务端的同时又是客户端
  • 一个 socket 可以在任何 point (不知道怎么翻译 point 才合适)上通过设置新属性的方式改变角色, 改变一个 socket 角色后,会影响接下来对这个 socket 做的所有 zmq_connect() 和 zmq_bind() 调用, 也就是说需要在这两个调用之前进行 curve 属性的设置。
  • 如果要把一个 socket 作为 curve server ,需要设置 ZMQ_CURVE_SERVER 和 ZMQ_CURVE_SECRETKEY 属性
  • 如果要把一个 socket 作为 curve client,需要设置 ZMQ_CURVE_SERVERKEY 以及 ZMQ_CURVE_PUBLICKEY、ZMQ_CURVE_SECRETKEY 这三个属性

2. 几行核心代码

想要使用 ZMQ curve 进行加密通信,需要在 ZMQ 的 server 端和 client 端进行相应的配置, 几行需要进行的配置代码如下:

2.1 curve server 端

 char szsecertkey[] = {};
char szpublickey[] = {}; //需要把这个 curve 公钥发给 client
zmq_curve_keypair(szpublickey, szsecertkey); int option = ;
zmq_setsockopt(sock, ZMQ_CURVE_SERVER, &option, sizeof(option));
zmq_setsockopt(sock, ZMQ_CURVE_SECRETKEY, szsecertkey, strlen(szsecertkey)); zmq_bind(sock, szaddr);

2.2 curve client 端

//这个 server_publickey 就是从 server 端拿到的 curve 公钥
zmq_setsockopt(sock, ZMQ_CURVE_SERVERKEY, server_publickey, strlen(server_publickey)); char szpubkey[] = {};
char szprikey[] = {};
zmq_curve_keypair(szpubkey, szprikey);
zmq_setsockopt(sock, ZMQ_CURVE_PUBLICKEY, szpubkey, strlen(szpubkey));
zmq_setsockopt(sock, ZMQ_CURVE_SECRETKEY, szprikey, strlen(szprikey)); zmq_connect(sock, szaddr);

3. 完整代码及执行
3.1 完整代码

代码链接: https://pan.baidu.com/s/1ytJdEa2VmYWfSx6mxIKYVw 提取码: ebyv

下载代码后,解压,执行编译命令:

g++ -g -o server server.c -lzmq -lpthread
g++ -g -o client client.c -lzmq

3.2 程序执行

代码演示了两个模式,一个是使用 curve 加密的传输模式,另一个是不使用 curve 加密的传输模式。 如果要使用 curve 加密的传输模式,需要在执行 server 和 client 程序的时候都加上 -s 参数。

1) 先执行 server

 [root@fengbo :: curve]$ ./server -s
server.c : test tZMQ with curve
server.c : szsecertkey = [I%43ZHg-Bnls&6rZ&)<J6hwGlD&I5l7]mi]{Ch-]
server.c : szpublickey = [kvIP^po{(kRL<eib#Zv=.cE%BpNom2DY#jl0-Ro[]
server.c : start secert comunication
server.c : recv msg : [I say ]
server.c : send msg : [I say , too]

2) 再执行 Client

 [root@fengbo :: curve]$ ./client -s
client.c : test tZMQ with curve
client.c : server publickey : [kvIP^po{(kRL<eib#Zv=.cE%BpNom2DY#jl0-Ro[]
client.c : start secert comunication
client.c : send msg : [I say ]
client.c : recv msg : [I say , too]

4. ZMQ curve 加密效果分析
通过对加密前与加密后的 ZMQ 消息进行 tcpdump 抓包,可以看到 ZMQ curve 的加密效果如何。

因为使用的是 127.0.0.1 作为测试地址,所以在使用 tcpdump 抓包的时候选择 lo 网口:

tcpdump -i lo -A -vv -X

4.1 加密前的抓包记录

对于不可打印的字符,tcpdump 都以点号 '.' 进行了显示

 ::49.788893 >.E.........
::07.333841 <.E.>.E.....
::49.788919 >.E.
::49.788990 <.E...........
::49.788997 >.E.
::49.789294 <.E............
::49.789303 >.E.
::49.789634 <.E...NULL................................................
::49.789875 >.E..NULL................................................
::49.789900 <.E..).READY.Socket-Type....DEALER.Identity....
::49.790309 >.E.
::49.790369 <.E..).READY.Socket-Type....DEALER.Identity......I.say.
::49.790561 >.E...I.say.,.too
::49.829945 <.E.

上面显示的信息是经过简化后的解析数据,不过可以看到 ZMQ 的两个 socket 之间通信的细节,例如可以看到几个 ZMQ 的关键字: DEALERSocket-TypeIdentity

以及 client 发送的数据 I say 1 ,和 server 返回的数据 I say 1, too。

很明显,数据在 ZMQ 中是以明文进行传输的。

4.2 加密后的抓包记录

::06.178841 ....>./........
::44.849972 ....>./>./....
::06.178864 >./>./
::06.178975 >./>./..........
::06.178982 >./>./
::06.179369 >./>./...........
::06.179376 >./>./
::06.180410 >.>./..NULL................................................
::06.180571 >.>..NULL................................................
::06.180588 >.>..).READY.Socket-Type....DEALER.Identity....
::06.181017 >.>.
::06.181064 >.>..).READY.Socket-Type....DEALER.Identity......request.publickey
::06.181191 >.>..((#65P{?aJEt@lWf/DDeQo@QX@gN{4nF3:?jz<^-
::06.183369 ....>.........
::02.029846 ....>.>.....
::06.183389 >.>.
::06.183485 >.>...........
::06.183491 >.>.
::06.183676 >.>............
::06.183681 >.>.
::06.184210 >.>...CURVE...............................................
::06.185457 >.>..CURVE...............................................
::06.188362 >.>....HELLO........................................................
....................{...:H_....."R&.....w.N..r..L...........Rv(b...F...
-+u.w....M...j).B.!<j.'...(..j...*..Qw........G.....c.....Y....:...
::06.190931 >.;>....WELCOME..6k.......,......a}.R..C.....>....|..a.z#...A[;..Yy..
..F`......k.......~...k.fDa./../.A7..m..J......i.b.......<.k.....T.....
..{......Y.........b..B....@w..t.MM
::06.196571 >.6A>.;........$.INITIATEX......fXA..{J%D<...O\.i?4.3$.../.../J#....ZpF
xZ...r...pj...C.&.k,...]`KF..|.i4.H(K..W..Fm".BU...........!...x....<..
....T....Z...6a....A....P.......c.V...........[E.n...|`@.~...aua..p...
#..N....._.....A....!.}....^Y2=..)..K.(.+.e6]..`..$;..k".g.].~.A.Hn
...GS%.U.ot..whb<..>..D\
::06.201254 >.6E>.6A.A.READY.........H.f.n....sS.....p\.y.ZM..F........l........wY.?G.
::06.202853 >.6G>.6E.(.MESSAGE..........t.oR..&:.SI..QI.m.....
::06.203034 >.6G>.6G.-.MESSAGE.............O]i........M....to....#
::06.220452 >.6Y>.
::06.242435 >.6o>.6G
::08.539483 >.?h>.6G.(.MESSAGE.........3n..l6~~..N.....\..[:T.
::08.539814 >.?h>.?h.-.MESSAGE...........<...A...Mq..=.........vs
::08.539824 >.?h>.?h

从 tcpdump 抓取的数据可以看到 CURVE 这样的字符,这说明 ZMQ 开始建立 curve 加密链接了。 不过在建立 curve 链接之前,有一个 client 向 server 请求公钥的操作,我们甚至可以在抓到的数 据中看到 server 发送给 client 的公钥 [(#65P{8?aJEt@lWf/DDeQo@QX@gN{4nF3:?jz<^-]。

因为传输公钥是在建立 curve 链接之前进行的, 所以我们还是可以看到明文数据的。

在上面的抓包数据中, CURVE 关键字出现的时候,就是 server 和client 开始进行 curve 链接的过程了, 可以看到这几个关键字:HELLO、WELCOME、INITIATEX、READY、MESSAGE。这些都是 ZMQ 的 curve 协议的一部分。

在上面的抓包数据中,我们没有看到 I say 1,也没有看到 I say 1, too。因为这些数据已经被加密传输了。 不过我们可以猜到,I say 1 和 I say 1, too 就跟在最后三行的两个 MESSAGE 的后面,只不过被加密了,我们看不到。


同步发表:https://www.fengbohello.top/archives/zeromq-curve

ZMQ示例:使用 curve 进行加密通信的更多相关文章

  1. 单片机上使用TEA加密通信(转)

    源:单片机上使用TEA加密通信 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:MDK4.72 单片机:STM32 说 ...

  2. 开源项目SMSS发开指南(四)——SSL/TLS加密通信详解

    本文将详细介绍如何在Java端.C++端和NodeJs端实现基于SSL/TLS的加密通信,重点分析Java端利用SocketChannel和SSLEngine从握手到数据发送/接收的完整过程.本文也涵 ...

  3. Oracle TDE的数据加密示例并用logminer验证加密效果

    1.确认数据库版本 2创建密钥钱包 3创建加密列的表并初始值 4演示TDE的数据加密示例 5 logminer验证加密效果

  4. bugzilla4的xmlrpc接口api调用实现分享: xmlrpc + https + cookies + httpclient +bugzilla + java实现加密通信下的xmlrpc接口调用并解决登陆保持会话功能

    xmlrpc .  https . cookies . httpclient.bugzilla . java实现加密通信下的xmlrpc接口调用并解决登陆保持会话功能,网上针对bugzilla的实现很 ...

  5. Crypto API加密通信流程

    应用程序使用Crypto API进行加密通信的一般步骤如下: 1,include wincrypt.h 2,调用CryptAcquireContext()获得某个CSP模块中的密钥容器(key con ...

  6. SSL及其加密通信过程

    SSL及其加密通信过程 什么是SSL SSL英文全称Secure Socket Layer,安全套接层,是一种为网络通信提供安全以及数据完整性的安全协议,它在传输层对网络进行加密.它主要是分为两层: ...

  7. Python3+ssl实现加密通信

    一.说明 1. python标准库ssl可实现加密通信 2. ssl库底层使用openssl,做了面向对像化改造和简化,但还是可以明显看出openssl的痕迹 3. 本文先给出python实现的soc ...

  8. RSA加密通信小结(二)-新版本APP与后台通信交互内容修改方案

    注1:本次修改分为两步,首先是内容相关的修改,待其完成之后,再进行加密通信项(粗体字备注)修改. 1.新的提交后台的格式包括:data,token(预留字段,暂时后台不校验),userId(已有的不删 ...

  9. RSA加密通信小结(一)

    一.背景描述 帮朋友完成相关方案的改进. 二.计划与方案 1.加密方式采用RSA 1024加密. 2.发送与接收都采用RSA加密,采用两套不同的密钥. 3.统一的加解码函数.(此处除了对于传输数据进行 ...

随机推荐

  1. Editor HDU - 4699 (栈)

    Problem Description   Sample Input 8 I 2 I -1 I 1 Q 3 L D R Q 2   Sample Output 2 3 Hint The followi ...

  2. CodeForces 371C Hamburgers(经典)【二分答案】

    <题目链接> 题目大意: 给以一段字符串,其中只包含"BSC"这三个字符,现在有一定量免费的'B','S','C‘,然后如果想再买这三个字符,就要付出相应的价格.现在总 ...

  3. BOM 和 DOM

    目录 一.BOM 1.什么是BOM 2. 浏览器内容划分 归BOM管的: 归DOM管的: 3. BOM常见方法 二.DOM 1 什么是DOM 2. DOM常见方法 一.BOM 1.什么是BOM BOM ...

  4. OSFPv3的配置

    实验目的 1.  掌握 OSPFv3 的配置方法 2.  掌握在帧中继环境下 OSPFv3 的配置方法 3.  掌握 OSPFv3 NSSA 的配置方法 4.  掌握外部路由汇总的配置 5.  掌握区 ...

  5. Java 浮点数精度丢失

    Java 浮点数精度丢失 问题引入 昨天帮室友写一个模拟发红包抢红包的程序时,对金额统一使用的 double 来建模,结果发现在实际运行时程序的结果在数值上总是有细微的误差,程序运行的截图: 输入依次 ...

  6. Java NIO- 最好文档

    http://www.cnblogs.com/puyangsky/p/5840873.html 1 背景介绍 在上一篇文章中我们介绍了Java基本IO,也就是阻塞式IO(BIO),在JDK1.4版本后 ...

  7. SpringBoot使用AOP

    本文介绍SpringBoot中使用Spring AOP. 简介 AOP简介 AOP可能对于广大开发者耳熟能详,它是Aspect Oriented Programming的缩写,翻译成中文就是:面向切面 ...

  8. C# 网络编程之基于SMTP发送电子邮件

     本文主要讲述基于C#网络编程的发送邮件的编程,邮件发送功能是基于邮件协议的,常见的电子邮件协议有SMTP(简单邮件传输协议).POP3(邮局协议).IMAP(Internet邮件访问协议),文章主要 ...

  9. Ubuntu下常用指令

    James最近因为需要尝试着编译Android源代码,系统环境变成了Ubuntu.和熟悉Windows操作系统环境一样,都有过渡的阶段.下面记录常用的操作指令. 分类目录如下: uname -a 查看 ...

  10. docker 导出导入镜像

    1.docker export jenkins > my_jenkins.tar   导出镜像到本地 cat my_jenkins | docker import my_jenkens:0.0. ...