SSH协议体系结构解读_第1页
SSH协议体系结构解读_第2页
免费预览已结束,剩余37页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、SSH协议体系结构解读 1、概念 SSH 的英文全称为 Secure Shell,是 IETF (Internet Engineering Task Force)的 Network Working Group所制泄的一族协议,其目的是要在非安全网络上提供安全的远程登录和其他 安全网络服务 q 如需要 SSH的详细信息请参考(SSH Communications Security Corporation 的网站)和(开放源码的OpenSSH组织的网站)。 2、基本框架 SSH协议框架中最主要的部分是三个协议:传输层协议、用户认证协议和连接协议。同时 SSH 协议框架中还为许多髙层的网络安全应用协

2、议提供扩展的支持。它们之间的层次关系可以用 如下图 1 来表示: 各种SSHW层网络安全应用协议 图 1 SSH协议的层次结构示意图 在 SSH的协议框架中,传输层协议(The Transport Layer Protocol)提供服务器认证,数 据机密性,信息完整性 等的支持:用户认证协议(The User Authentication Protocol)则 为服务器提供客户端的身份鉴别:连接协议(The Connection Protocol)将加密的信息隧 道复用成若个逻借通道,提供给更高层的应用协议使用:各种高层应用协议可以相对地独 立于 SSH 基本体系之外,并依靠这个基本框架,通过

3、连接协议使用 SSH的安全机制。 3、主机密钥机制 对于 SSH这样以提供安全通讯为目标的协议,英中必不可少的就是一套完备的密钥机制。由 于SSH协议是面向互联网网络中主机之间的互访与信息交换,所以主机密钥成为基本的密钥 机制。也就是说,SSH协议要求每一个使用本协议的主机都必须至少有一个自己的主机密钥 对,服务方通过对客户方主机密钥的认证之后,才能允许苴连接请求。一个主机可以使用多 个密钥,针对不同的密钥算法而拥有不同的密钥,但是至少有一种是必备的,即通过 DSS 算法产生的密钥。关于 DSS算法,请参考FIPS-186 o SSH协议关于主机密钥认证的管理方案有两种,如下图 2 所示:连接

4、协议 用户认证协议 传输层协议 服务器认证 数据机密性 信息気整性 图 2 SSH主机密钥管理认证方案示意图 每一个主机都必须有自己的主机密钥,密钥可以有多对,每一对主机密钥对包括公开密钥和 私有密钥。在实际应用过程中怎样使用这些密钥,并依赖它们来实现安全特性呢?如上图所 示,SSH协议框架中提岀了两种方案。 在第一种方案中,主机将自己的公用密钥分发给相关的客户机,客户机在访问主机时则使用 该主机的公开密钥来加密数拯,主机则使用自己的私有密钥来解密数据,从而实现主机密钥 认证,确泄客户机的可靠身份。在图 2 (a)中可以看到,用户从主机 A 上发起操作,去访 问,主机 B 和主机 C,此时,A

5、 成为客户机,它必须事先配置主机 B和主机 C 的公开密钥, 在访问的时候根据主机名来査找相应的公开密钥。对于被访问主机(也就是服务器端)来说 则只要保证安全地存储自己的私有密钥就可以了。 在第二种方案中,存在一个密钥认证中心,所有系统中提供服务的主机都将自己的公开密钥 提交给认证中心,而任何作为客户机的主机则只要保存一份认证中心的公开密钥就可以了。 在这种模式下,客户机在访问服务器主机之前,还必须向密钥认证中心请求认证,认证之后 才能够正确地连接到目的主机上。 很显然,第一种方式比较容易实现,但是客户机关于密钥的维护却是个麻烦事,因为每次变 更都必须在客户机上有所体现:第二种方式比较完美地解

6、决管理维护问题,然而这样的模式 对认证中心的要求很高,在互联网络上要实现这样的集中认证,单单是权威机构的确定就是 个大麻烦,有谁能够什么都能说了算呢?但是从长远的发展来看,在企业应用和商业应用领 域,采用中心认证的方案是必要的。 期外,SSH协议框架中还允许对主机密钥的一个折中处理,那就是首次访问免认证。首次访 问免认证是指,在某客户机第一次访问主机时,主机不检查主机密钥,而向该客户都发放一 个公开密钥的拷贝,这样任以后的访问中则必须使用该密钥,否则会被认为非法而拒绝其访 问。 4、字符集和数据类型 SSH协议为了很好地支持全世界范用的扩展应用,在字符集和信息本地化方面作了灵活的处 理。首先,

7、SSH协议规泄,其内部算法标识、协议名字等必须采用 US-ASCII字符集,因为 这些信息将被协议本身直接处理,而且不会用来作为用户的显示信息。英次,SSH 协议指左 了通常情况下的统一字符集为 ISO 10646 标准下的 UTF-8 格式,详细请参考 RFC-2279。另 外,对于信息本地化的应用,协议规左了必须使用一个专门的域来记录语言标记(Language Tag)。对于大多数用来显示给用户的信息,使用什么样的字符集主要取决于用户的终端系 统,也就是终端程序及苴操作系统环境,因而对此 SSH 协议框架中没有作硬性规泄,而由具 体实现协议的程序来自由掌握。 除了在字符、编码方面的灵活操作

8、外,SSH 协议框架中还对数据类型作了规泄,提供了七种 方便实用的种类,包括字节类型、布尔类型、无符号的 32 位整数类型、无符号的 64 位整数 类型、字符串类型、多精度整数类型以及塔字表类型。下而分别解释说明之: (1) 字节类型(byte) 一个字节(byte)代表一个任意的 8 字位值(octet) RFC-1700。有时候固上长度的数据 就用一个字节数组来表示,写成 bytetn的形式,其中 n 是数组中的字节数屋。 (2) 布尔类型(boolean) 一个布尔值(boolean)占用一个字节的存储空间。数值 0 表示“假”(FALSE),数值 1 表示“真”(TRUE)。所有非零的

9、数值必须被解释成“真”,但在实际应用程序中是不能给 布尔值存储 0 和 1 意外的数值。 (3) 无符号的 32 位整数类型(unit32) 一个 32 字位的无符号整型数值,由按照降序存储的四个字节构成(降序即网络字廿序,高 位在前,低位在后)。例如,有一个数值为,它的十六进制表示为 0 x03CDF3B9,在实际存 储时就是 03 CD F3 B9,具体存储结构的地址分配如图 3。 03 CD F3 B9 unit32首地址为;OzlOOO 0 x1000 0 x1001 0 x1002 0 x1003 图 3 无符号 32 位整数类型的典型存储格式 (4) 无符号的 64 位整数类型(u

10、nit64) 一个 64 字位的无符号整型数值,由按照降序存储的八个字节构成,其具体存储结构与 32 位整数类似,可以比照图 3。 (5) 字符串类型(string) 字符串类型就是任意长度的二进制序列。 字符串中可以包含任意的二进制数据, 包括空字符 (null)和 8 位字符。字符串的前四个字节是一个 unit32 数值,表示该字符串的长度(也 就是随后有多少个字节),unit32 之后的零个或者多个字节的数据就是字符串的值。字符 串类型不需要用空字符来表示结束。 字符串也被用来存储文本数据。这种情况下,内部名字使用 US-ASCII字符,可能对用户显 示的文本信息则使用 ISO-1064

11、6UTF-8 编码。一般情况字符串中不应当存储表示结束的空字 符(null)。 在图 4 中举例说明字符串My ABC”的存储结构: 00 00 00 06 4D 79 20 41 42 43 宇符串(string)首地址为;OKIOOO 0 x1000 0 x1001 01002 0 x1003 本字符串的实际內容,共天个字 符,不需要结束的 XL 空字符 一个表示車字符串数据长度的 32位无符号整数 (长度为0 x00000006,即 G 图 4 字符串类型的典型存储格式 从图4中可以很明显地看出, 字符串类型所占用的长度为4个字节加上实际的字符个数(字 节数),即使没有任何字符的字符串也

12、要占用四个字节。这种结构与 Pascal 语言中的字符 串存储方式类似。 (6)多精度整数类型(mpint) 多精度的整数类型实际上是一个字符串,其数据部分采用二进制补码格式的整数,数拯部分 每个字节 8 位,高位在前,低位在后。如果是负数,其数据部分的第一字节最髙位为 1。如 果恰巧一个正数的最高位是 1 时,它的数据部分必须加一个字节 0 x00作为前导。需要注意 的是,额外的前导字节如果数值为 0 或者 255 时就不能被包括在整数数值内。数值 0 则必须 被存储成一个长度为零的字符串(string) 多精度整数在具体运算时还是要遵循正常的整 数运算法则的。 其存储格式通过图 5 的若干

13、示例来说明: 00 00 00 00 (a)多精度的整数0 00 00 00 02 00 FF 指示数据长度为2宇节 实际数据ikFF (b)多精度的整数氐ff,最高位是呗J加前导字节氐叽 00 00 00 02 32 1D 4F 97 03 2A 11 CO七个字节的多精度的整数,正数数据部分无需前导字节 00 00 00 02 FC A8 00 00 00 04 FF 54 32 11 (4)多精度整数的负数表示,上面为-0 x0358,补码为OzFCAS,最高位已 经是1 (QxFC),不要前导空格;下侖为是0 xABCDEF,补码为0/43211, 由于其最高为不是(0 x54),所以

14、加前导宁节OzFF 图 5 多精度整数类型的典型存储格式 (7)名字表类型(name-list) 名字表(name-list)是一个由一系列以逗号分隔的划字组成的字符串(string)。在存储 方式上与字符串一样,名字表前四个字节是一个 unit32 型整数以表示英长度(随后的字节 数目,类似于字符串类型),其后跟随着由逗号分隔开的一系列名字,可以是 0 个或者多个。 一个名字则必须具有非实际数据血321D4F97032A11 指示数据畏度为7字节 零长度,而且不能包含逗号,因为逗号是鋼字之间的分隔符。在使用 时,上下文关系可以对划字表中的名字产生额外的限制,比如,一个拿字表中的需字都必须 是

15、有效的算法标识,或者都是语言标记等。需字表中轻字是否与顺序相关,也要取决于该名 字表所在的上下文关系。与字符串类型一样,无论是单个的划字,还是整个名字表,都不需 要使用空字符作为结束。如下图 6: 00 00 00 00 指示数据长度为0字节 a)个空的名字表 00 00 00 07 73 73 68 2c 72 73 61 1 1 C 9 中 C 9 、 9 9 S S r S a 指示数据长度为2字节 表中第一个名字飞 sh 表中第二个名字& sa _ I _ 名字一和爸字二之间的分隔符 (b)具有两个名字的名字表,讯 11”和卞丫 图 6 名字表的典型存储格式 SSH协议框架中拥有对这些

16、数据类型的支持,将对协议、算法的处理带来极大的便利。 5、命划规则及消息编码 SSH协议在使用到特定的哈希算法,加密算法,完整性算法,压缩算法,以及密钥交换算:法 和其他协议时都利用轻字来区分,所以 SSH协议框架中很重要的一个部分就是命斜规则的限 左。无论是 SSH协议框架中所必备的算法或者协议,还是今后具体应用实现 SSH协议时增加 的算法或者协议,都必须遵循一个统一的命名规则。 SSH协议框架对命乞规则有一个基本原则:所有算法标识符必须是不超过 64 个字符的非空、 可打印 US-ASCII字符串;名字必须是大小写敏感的。 具体的算法命名有两种格式: (1) 不包含符号的名字都是为 IE

17、TF标准 (RFC 文档) 保留的。 比如, “3des-cbc” , “sha-l”,“hmac-shal”,“zlib”(注意:引号不是名字的一部分)。在没有事先注册 之前,这种格式的名字是不能使用的。当然 IETF 的所有注册的划字中也不能包含符号或者 逗号。 (2) 任何人都可以使用“namedomainnarne”的格式命名自定义的算法,比如。在符 号之前部分的具体格式没有限立,不过这部分中必须使用除符号和逗号之外的 US-ASCII 字符。在符号之后的部分则必须是一个完全合法的 Internet域划(参考RFC-1034),个 人域需和组织域划均可。至于局部需字空间的管理则是由各个

18、域自行负责的。 SSH协议框架中另一个主要的标准化规则就是消息编码,基本规左在表 1 中详述: 协这分类 用途 传输层协仪 1-19 传输层基本消息(比如,斷卄连接,忽 略,调试等等) 20-29 算法协商 30-49 密钥交换方法的细节区分 用户认证协议 50-59 用尸认址基本消息 60-79 用尸认址方法的细节 连接协议 80-89 连接协议基本消息 90-127 通道有关的消息 客户端协仪 128-191 保綃为客户端协议所用 本地扩展 192-255 本地扩展功能时便用的编号 表 1 SSH协议框架中的编码范国原则 6、SSH协议的可扩展能力 SSH协议框架中设计了大量可扩展的冗余能

19、力,比如用户自左义算法、客户自立义密钥规则、 髙层扩展功能性应用协议等,在本文中将不一一赘述。值得一提的是,这些扩展大多遵循 IANA (Internet Assigned Numbers Authority)的有关规定,特别是在重要的部分,象命 名规则和消息编码方面。关于 IANA 的标准及组织情况请访问该组织的官方网站:。 协议浅析 第一部分:协议概览 整个通讯过程中,经过下而几个阶段协商实现认证连接。 第一阶段: 由客户端向服务器发岀 TCP连接请求。TCP连接建立后,客户端进入等待,服务器向客 户端发送第一个报文,宣告自己的版本号,包括协议版本号和软件版本号。协议版本号由主 版本号和次

20、版本号两部分组成。它和软件版本号一起构成形如: SSH-主协议版本号次协议版本号 - 软件版本号n 的字符串。其中软件版本号字符串的最大长度为 40 个字节,仅供调试使用。客户端接到报 文后,回送一个报文,内容也是版本号。客户端响应报文里的协议版本号这样来决定:当与 客户端相比服务器的版本号较低时,如果客户端有特泄的代码来模拟,则它发送较低的版本 号:如果它不能,则发送自己的版本号。当与客户端相比服务器的版本号较髙时,客户端发 送自己的较低的版本号。按约定,如果协议改变后与以前的相兼容,主协议版本号不变:如 果不相兼容,则主主协议版本号升高。 服务器接到客户端送来的协议版本号后,把它与自己的进

21、行比较,决左能否与客户端一起工 作。如果不能,则断开 TCP连接:如果能,则按照二进制数据包协议发送第一个二进制数 拯包,双方以较低的协议版本来一起工作。到此为止,这两个报文只是简单的字符串,你我 等凡人直接可读。 第二阶段: 协商解决版本问题后,双方就开始采用二进制数据包进行通讯。由服务器向客户端发送第一 个包,内容为自己的 RSA 主机密钥(host key)的公钥部分、RSA 服务密钥(server key)的公钥 部分、支持的加密方法、支持的认证方法、次协议版本标志、以及一个 64 位的随机数 (cookie)0这个包没有加密,是明文发送的。客戸端接收包后,依据这两把密钥和被称为 co

22、okie 的 64 位随机数计算出会话号(session id)和用于加密的会话密钥(session key)o随后客户端回 送一个包给服务器,内容为选用的加密方法、cookie 的拷贝、客户端次协议版本标志、以及 用服务器的主机密钥的公钥部分和服务密钥的公钥部分进行加密的用于服务器汁算会话密 钥的 32 字节随机字串。除这个用于服务器讣算会话密钥的 32 字节随机字串外,这个包的 其他内容都没有加密。之后,双方的通讯就是加密的了,服务器向客户端发第二个包(双方 通讯中的第一个加密的包)证实客户端的包已收到。 第三阶段: 双方随后进入认证阶段。可以选用的认证的方法有: (l)/.rhosts

23、或/etc/认证(缺省配置时不容许使用它); 用 RSA 改进的/.rhosts 或/etc/认证; (3) RSA 认证; (4) 口令认证。 如果是使用rhosts 或/etc/进行认证,客户端使用的端口号必须小于 1024。 认证的第一步是客户端向服务器发 SSH_CMSG_USER 包声明用户名,服务器检查该用户 是否存在 , 确 左 是 否 需 要 进 行 认 证 。 如 果 用 户 存 在 , 并 且 不 需 要 认 证 , 服 务 器 回 送 一 个 SSH_SMSG_SUCCESS 包,认证完成。否则,服务器会送一个 SSH_SMSG_FAILURE包, 表示或是用户不存在,或

24、是需要进行认证。注意,如果用户不存在,服务器仍然保持读取从 客户端发来 的 任 何 包 。 除 了 对 类 型 为SSH_MSG_DISCONNECT. SSH_MSG_IGNORE 以 及SSH_MSG_DEBUG 的包外,对任何类型的包都以 SSH_SMSG_FAILURE 包。用这种 方式,客户端无法确泄用户究竟是否存在。 如 果 用 户 存 在 但 需 要 进 行 认 证 , 进 入 认 证 的 第 二 步 。 客 户 端 接 到 服 务 器 发 来 的 SSH_SMSG_FAILURE 包后,不停地向服务器发包申请用各种不同的方法进行认证,直到 时限已到服务器关闭连接为止。时限一般设

25、泄为 5 分钟。对任何一个申请,如果服务器接 受,就以SSH_SMSG_SUCCESS 包回应;如果不接受,或者是无法识別,则以 SSH_SMSG_FAILURE 包回应。 第四阶段: 认证完成后,客户端向服务器提交会话请求。服务器则进行等待,处理客户端的请求。在这 个阶段,无论什么请求只要成功处理了,服务器都向客户端回应 SSH_SMSG_SUCCESS 包; 否则回应 SSH_SMSG_FAILURE 包,这表示或者是服务器处理请求失败,或者是不能识别 请求。会话谙求分为这样几类:申请对数据传送进行压缩、申请伪终端、启动 XII、TCP/IP 端口转发、启动认证代理、运行 shell、执行

26、命令。到此为止,前面所有的报文都要求 IP的 服务类型(TOS)使用选项 IPTOS_THROUGHPUT。 第五阶段: 会话申请成功后,连接进入交互会话模式。在这个模式下,数据在两个方向上双向传送。此 时,要求 IP的服务类型(TOS)使用 IPTOS_LOWDELAY 选项。当服务器告知客户端自己 的退出状态时,交互会话模式结朿。 (注意:进入交互会话模式后,加密被关闭。在客户端向服务器发送新的会话密钥后,加密 重新开始。用什么方法加密由客户端决定。) 第二部分:数据包格式和加密类型 二进制数据包协议: 包=包长域(4 字节:u_int32)+填充垫(1-7 字节) +包类型域(1 字疔:

27、u_char) +数据域 +校验和域(4 字节) 加密部分=填充垫+包类型+数据+校验和 包长=1(包类型)+数据字节长度+4(校验和) 数据包压缩: 如果支持压缩,包类型域和数据域用 gzip压缩算法进行压缩。压缩时在两个数据传送方向 的任何一个上,包的压缩部分(类型域+数据域)被构造得象是它连在一起,形成一个连续的 数据流。在两个数据传送方向上,压缩是独立进行的。 数据包加密: 现时支持的数据加密方法有这样几种: SSH_CIPHER_NONE 0 不进行加密 SSH_CIPHER_IDEA 1 IDEA 加密法(CFB 模式) SSH_CIPHER_DES 2 DES 加密法(CBC 模

28、式) SSH_CIPHER_3DES 3 3DES 加密法(CBC 模式) SSH_CIPHER_ARCFOUR 5 Arcfour 加密法) SSH_CIPHER_BLOWFISH 6 Blowfish 加密法 协议的所有具体实现都要求支持 3DES。 DES加密: 从会话密钥中取前 8 个字节,每个字只用高 7 位,忽略最低位,这样构成 56 位的密钥供加 密使用。加密时使用 CBC 模式,初使矢量彼初始化为全零。 3DES加密: 3DES是 DES的变体,它三次独立地使用 CBC 模式的 DES加密法,每一次的初始矢量 都是独立的。第一次用 DES加密法对数据进行加密;第二次对第一次加密

29、的结果用 DES加 密法进行解密:第三次再对第二次解密的 结用 DES加密法进行加密。注意:第二次解密的结果并不就是被加密的数据,因为三次使 用的密钥和初始矢量都是分别不同的。与上而的 DES加密采用的方法类似,第一次从会话 密钥中取起始的前 8 个字节生成加密密钥,第二次取下一个紧跟着的 8 个字节,第三次取再 下一个紧跟着的 8 个字节。三次使用的初始矢量都初始化为零。 IDEA 加密: 加密密钥取自会话密钥的前 16 个字节,使用 CFB模式。初始矢量初始化为全零。 RC4 加密: 会话密钥的前 16 个字节被服务器用作加密密钥,紧接着的下一个 16 字节被客户端用作加密 密钥。结果是两

30、个数据流方向上有两个独立的 129 位密钥。这种加密算法非常快。 第二部分:密钥的交换和加密的启动 在服务器端有一个主机密钥文件,它的内容构成是这样的: 1. 私钥文件格式版本字符串; 2. 加密类型(1 个字节); 3. 保留字(4 个字节): 4.4个字节的无符号整数; 5. nip 型整数; 6. mp 型整数; 7. 注解字符串的长度: 8. 注解字符串: 9. 校验字(4 个字节): 10. mp 型整数: 11. mp 型整数; 12. mp 型整数; 13. mp 型整数: 其中 4、5、6 三个字段构成主机密钥的公钥部分;10、11、12、13 四个字段构成主机密钥 的私钥部分

31、。9、10、11、12、13 五个字段用字段 2 的加密类型标记的加密方法进行了加 密。4 个字节的校验字交叉相等,即第一个字节与第三个字节相等,第二个字节与第四个字 肖相等。在服务器读取这个文件时进行这种交叉相等检査,如果不满足这个条件,则报错退 出。 服务器程序运行的第一步,就是按照上而的字段划分读取主机密钥文件。随后生成一个随机 数,再调用函数 void rsa_generate_key RSAPrivateKey *prv, RSAPublicKey 幺 pub. RandomState *state, unsigned int bits ): 生成服务密钥,服务密钥也由公钥和私钥两部

32、分组成。上而的这个函数第一个指针参数指向 服务密钥的私钥部分,第二个指向公钥部分。然后把主机密钥的公钥部分和服务密钥的公钥 部分发送给客户端。在等到客户端回应的包后,服务器用自己的主机密钥的私钥部分和服务 密钥的私钥部分解密得到客户端发来的 32 字节随机字串。然后 il算自己的会话号,并用会 话号的前16 字节 xor 客户端发来的 32 字节随机字串的前 16 字节,把它作为自己的会 话密钥。注意,服务器把 8 个字节的 cookie.主机密钥的公钥部分、和服务密钥的公钥部 分作为参数来计算自己的会话号。 再来看客户端。客户端启动后的第一步骤也是读取主机密钥。然后等待服务器主机密钥、服 务

33、密钥、和 8 个字节的 cookie.,注意,服务器发送来的只是主机密钥和服务密钥的公钥部 分。接到包后,客户端立即把从服务器端收到 cookie、主机密钥、和服务密钥作为参数讣算 出会话号。从上而可以看出,服务器和客户端各自计算出的会话号实际是一样的。 随后,客户端检查用户主机列表和系统主机列表,查看从服务器收到的主机密钥是否在列表 中。如果不在列表中,则把它加入列表中。然后就生成 32 字节的随机字串,这个 32 字节 的随机字串就是客户端的会话密钥。客户端用 16 字节的会话密钥 xor它的前 16 字节, 把结果用服务器的主机密钥和服务密钥进行双重加密后发送给服务器。产生 32 字节随

34、机字 串时,随机数种子由两部分组成,英中一部分从系统随机数种子文件中得到,这样来避免会 话密钥被猜出。从上而服务器和客户端各自计算会话密钥的过程可以看岀,服务器和客户端 计算岀的会话密钥是一样的。 上而的这几步,总结起来就要交换确定会话密钥,因为无论是 des、idea、3dcs、arefour、 还是blowfish 都是对称加密方法,只有一把密钥,双方都知道了会话密钥才能启动加密。 但会话密钥不能在网络上明文传送,否则加密就失去意义了。于是使用 RSA 公钥体系对会 话密钥进行加密。 RSA 公钥体系的办法是用公钥加密私钥解密,它依据这样的数学左理: 若 p、q 是相异的两个质数,整数 r

35、和 m满足 rm = 1 (mod (p-l)(q-l) a 是任意的整数,整数 b、c满足 b = aAm (mod pq)? c = bW (mod pq) 则 c = a (mod pq)。 具体实现是这样的: (1)找三个正整数 p、q、r,其中 p、q 是相异的质数, r是与(p-1)、(q-1)互质的数。这三个数 p、q、r 就是私钥(private key)。 再找一个正整数 m满足 rm= 1 (mod(p-l)(q-l)。 计算 n = pq, m、n 就是公钥(public key)o 被加密对象 a 看成是正整数,设 a=n, 将 a 表示成 s(sn,通常取 s = 2

36、At)进制的, 然后对每一位分别编码。 (4) 加密:计算 b = aAm (mod n) (0 = b n), b 为 加密结果。 (5) 解密:计算 c = bAr (mod n) (0 = c q); nipzjnit( &prv-p); mpzjnit(&prvc); nipzjnit( &prv-d); mpzjnit(&prvu); inpzjnit(&prvn); nipzjnit(&tcst); mpz_init(&aux); /*计算质数 p、q 的位数*/ pbits = bits / 2; qbits = bits - pbits; rctryO: fprintf(std

37、err. Generating p:H); /*生成随机质数 p*/ rsa_random_prime(&prvp, state, pbits); retry: fprintf(stderr. MGencrating q:H); /*生成随机质数 q*/ rsa_random_prime(&prvq, state, qbits); /*判断是否 p = q,如果是返回重新生成*/ ret = mpz_cmp(&prvp, &prv-q); if (ret = 0) fprintf(stdcrr. ”Generated the same prime twice!nH); goto retry;

38、if (ret 0) mpz_set(&aux. &prv-p): mpz_scl(&prvp, &prv-q); mpz_sct(&prvq. &aux); ) /*确泄 p、q 是否很接近*/ mpz_sub(&aux, &prv-q, &prvp); mpz_div_2exp(&test9 &prv-q, 10); if (mpz_cmp(&aux, &tcst) p, &prv-q); if (mpz_cmp_ui(&auxt 1) !=0) fprintf(stderr. HThc primes are not relatively prime!nM); goto retry; /*

39、从质数 p、q 导岀私钥*/ fprintf(stderr. Computing the keys.nn): dcrive_rsa_keys(&prvn, &prv-e, &prv-d, &prv-u. &prvr-p. &prvq, 5); prv-bits = bits; /*从质数 p、q 导岀公钥*/ pub-bits = bits; mpzjnit_set(&pub-n. &prvr-n); mpzjnit_set(&pubc. &prvc);mpz_clear(&aux); /*测试公钥和密钥是否有效*/ fprintf(stderr. HTesting the keys.nH);

40、 rsa_random_integer(&tcsl, state, bits); mpz_mod(&(csi. &tcst, &pub-n); /* must be less than n. */ rsa_private(&aux. &test, prv); rsa_public(&aux, &aux, pub); if (mpz_cmp(&aux, &test) != 0) fprintf(stdcrr. * private+public failed to dccrypt.nM); goto retryO; rsa_public(&aux, &test, pub); rsa_private

41、(&aux. &aux prv); if (mpz_cmp(&aux, &test) != 0) fprintf(stderr. public+private failed to decry pt.n ); goto retryO; mpz_clcar(&icst);mpz_set_ui(&aux. 3); fprintf(stdcrr. Key generation complete 在上而的函数成一对密钥时,首先调用函数 void rsa_random_prime ( MP_INT *ret, RandomState *state, unsigned int bits ) MP_INT s

42、tart, aux; unsigned int num_primes; int * moduli; long difference; nipzjnit(&staH); mpzjnit(&aux); retry: /*挑出一个随机的足够大的整数*/ rsa_random_integer(&start. state, bits); /*设置最髙的两位*/mpz_mod_ui(&aux. &start. small_primesnum_priines); mpz_muL2exp(&aux, &aux, bits - 2); mpzjor(&start, &start, &aux); /*设置最低的两

43、位为奇数*/ inpz_set_ui(&aux, 1); mpzjor(&start, &start, &aux); /*启动小质数的 moduli数*/ moduli = malloc(MAX_PRIMES_IN_TABLE * sizeof(moduli0); if (moduli = NULL) printf(stderr, MCannl get memory for modulinH); exit(l); if (bits Ox) fprintf(stdcrr. nrsa_random_prime:M failed to find a prime. retrying.nH); if (

44、moduli != NULL) free(moduli); else exit(l); goto retry; ) /*检查它是否是小质数的乘积*/ for (i = 0; i = small_primesi) modulii -= small_primesi; if (modulifi + difference = 0) break: if (i num_primes) continue; /* Multiple of a known prime */ /*检查通过*/ fprintf(stderr, N.H); /* Compute the number in question. */ m

45、pz_add_ui(ret, &start. difference); /* Perform the fermat test for witness 2. This means: it is not prime if 2An mod n != 2. */ mpz_set_ui(&aux, 2); mpz_powm(&aux, &aux, ret, ret); if (mpz_cmp_ui(&aux, 2) = 0) /* Passed the fermat test for witness 2. */ fprintf(stdcrr. n+M); /* Perform a more tests.

46、 These are probably unnecessary */ if (mpz_probab_prime_p(ret. 20) break; /* It is a prime with probability 1 2A-40. */ /* Found a (probable) prime. It is in ret. */ fprintf(stderr. ” + (distance %ld)nM, difference); /* Free the small prime moduli; they are no longer needed/ if (moduli != NULL) free

47、(moduli); else exit(l); /* Sanity check: does it still have the high bit set (we might have wrapped around)? */ mpz_div_2cxp(&aux, ret. bits 1); if (mpz_get_ui(&aux) != 1) fprintf(stdcrr. Mrsa_random_pnme: high bit not set, retrying.nM); goto retry; ) mpz_clear(&start); mpz_clcar(&aux); 随机产生一对大质数(p.

48、q)o这对随机大质数要符合的条件是p必须小于q“然后调用下而 的函数来生成公钥和私钥对的其他组员: static void derive_rsa_keys MPJNT *n. MPJNT *e, MPJNT *d. MP_INT *u, MPJNT *p. MPJNT *q, unsigned int ebits ) MPJNT p_minus_l, q_minus_l, aux, phi. G. F: asscrt(mpz_cmp(p. q) = 0) fprintf(stderr. Warning: G= ); mpz_out_str(stdout, 10, &G); fprintf(st

49、dcrr. is large (many spare key sets); key may be bad!n”); /* F = phi / G; the number of relative prime numbers per spare key set. */ mpz_div(&F. &phi. &G); /* Find a suitable e (the public exponent). */ mpz_sct_ui(c, 1); mpz_mul_2cxp(c, e, ebits); mpz_sub_ui(e, e, 1); /*make lowest bit 1. and substr

50、act 2.*/ /* Keep adding 2 until it is relatively prime to (p-D(q-l ). */ do mpz_add_ui(e e, 2); mpz_gcd(&aux, e, &phi); while (mpz_cmp_ui(&aux, 1) !=0); /* d is the multiplicative inverse of c, mod F. Could also be mod (p-l)(q-l); however, we try to choose the smallest possible d */ mpz_modjnverse(d

51、, e, &F); /* u is the multiplicative inverse of p, mod q, if p q. It is used when doing private key RSA operations using the Chinese remainder theorem method. */ mpz_mod_inverse(u. p. q); /* n = p * q (the public modulus). */ mpz_mul(n, p. q); /* Clear auxiliary variables. */ mpz_clear(&p_minus_l);

52、mpz_clear(&q_ minus_l); mpz_clear(&aux); mpz_clcar(&phi); mpz_clear(&G); mpz_clcar(&F); 最后为检验所生成的一对密钥的有效性,它调用下面的函数产生一个随机整数。 void rsa_randomJnteger(MP_INT *ret, RandomState *state, unsigned int bits) unsigned int bytes = (bits + 7)/8; char *str = xmalloc(bytes * 2 + I); unsigned int i; /*生成一个适当大小的 16

53、 进制随机数,把它转化成 mp型整数*/ for (i = 0; i bytes; i+) sprintf(str + 2 * i, H%02xH, random_get_byte(state); /*转化到内部表示*/ if (mpz_seLstr(ret, str, 16) = 4; i -= 4) unsigned long limb = mpz_get_ui(&aux); PUT_32BIT(buf+i-4, limb); mpz_div_2cxp(&aux. &aux. 32); ) for (; i 0; i-) buffi - 1 = mpz_gct_ui(&aux); mpz_

54、div_2cxp(&aux. &aux, 8); mpz_clear( &aux); 随后客户端汁算会话密钥,计算过程是首先生成 32 个字节即 256位随机字串: for (i = 0; i 32; i+) session_keyi = random_get_byte(state); 然后用 16 字节的会话号 xor这 32 字的随机字串的前 16 字节,并安 msb 次序来排列构成 一个MP型整数: mpzjnit_set_ui(&kcy. 0); for (i = 0; i 32; i+) mpz_mul_2cxp(&kcy, &key, 8); if(i/usr/openwiii/b

55、in/xauth list *.*.*/unix:10MIT-MAGIC-COOKIE-l 92b404c556588ced6clacd4ebf053f68 *.*.*/unix:ll MIT-MAGIC-COOKIE-1 92b404e556588ced6clacd4ebf053f68 *.*: 10 MIT-MAGIC-COOKIE-1 92b404e556588ced6c 1 acd4ebf053f68 和*性“*/imix: 10 MIT-MAGIC-COOKIE-1 92b404e556588ced6c lacd4cbf053f68 *.*: 11 MIT-MAGIC-COOKIE-

56、1 92b404e556588ced6c 1 acd4ebf053f68 *.* */unix: 11 MIT-MAGIC-COOKIE-1 92b404e556588ced6clacd4ebf053f68 wangdb /home/wangdb echo SDISPLAY *.*: 10.0 wangdb /home/wangdb /usr/opcnwin/bin/xauth Using authority file /liome/wangdb/.Xauthority xauth list *.*: 10.0 *.*: 10 MIT-MAGIC-COOKIE-1 92b404e556588c

57、ed6c 1 acd4ebf053f68 xauth quit wangdb /home/wangdb .Xauthority文件的显示记录里各个字段的含义如下,第一个字段的*.*是主机划, ”:”号后的前而的数字是 X 服务器标号,”.后而的数字是显示屏幕(显示器)标号。这个字 段称为显示斜,SDISPLAY 环境变量里填入这个字段。第二个字段是协议标号,第三个字 段是十六进制的认证钥。认证钥是由系统给的,打开 X 显示时如果认证钥给的不对,X 服 务器拒绝处理显示请求。 ssh 实现 X 转发的第一步是,客户端调用 popcn 函数执行xauth list SDISPLAY命令, 读取 X

58、 显示的屏幕号、协议号、和认证钥,然后把协议号和认证钥保存在内存中。客户端 并不把自己的认证钥发送给服务器,而是生成一个 8 位二进制随机数序列,以十六进制打 印,把这个十六进制数字串发送给服务器作为认证钥。等到服务器发来打开 X 显示请求时, 客户端使用自己真正的认证钥打开 X 显示。采用这种方法,客户保证了自己的认证钥不会 泄露给外界,安全性得到保证。 服务器接到客户端的 X 转发请求后,读取客户端发来的屏幕号、协议号、和认证钥,然后 打开一个 socket并绑左它,设置成侦听模式,并用这个 socket 设置一个通道。随后就从 服务器自己的配置文件读岀 X 服务器标号,调用 gethos

59、tname函数获取本机主机爼,把这 两者和客户发来的屏幕号结合在一起构成显示列表记录的第一字段。 在服务器处理客户端执行命令或启动 shell的请求时,它用前而设宜的通道接受一个 TCP 连接,返回一个 socket,再用这个 socket 设置一个新通道。然后发一个包给客户端要求它 打开一个 X 显示。客户端接到这个包后打开一个 socket 与本地 X 服务器连接,即打开一 个 X 显示: int display.numben sock; const char * display; struct sockaddr_un ssun; /* Try to open a socket for t

60、he local X server. */ display = getenv(uDISPLAYH); if (!display) error(MDISPLAY not set.H); goto fail; /* Now we decode the value of the DISPLAY variable * and make a connection to the real X serx er. */ /* Check if it is a unix domain socket. Unix domain * displays are in one of the following forma

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论