1. 暗网的创建与访问

假定HS服务提供商为Bob,访问暗网的用户为Alice

1.1 Hidden Service

(1)Bob首先配置自己的Tor Onion Proxy(OP)并自动生成RSA-1024密钥对,然后将经过ASN.1格式序列化的RSA公钥通过SHA-1哈希(输出160bit),并截取其前半部分(80bit,也就是10bytes)成为Bob的隐藏服务描述符唯一标识(HS Descriptor ID)。然后将其通过base32编码成为16个字符(v2 onion address中为16个字符,v3中则为56个字符,详细分析看后文)并与".onion"拼接成为我们常见的暗网地址。

此时Bob选取一些Tor节点(此处我认为是3个,尚不确定)作为其介绍节点(Introduction Point, 简称IP),并与每个IP建立Introduction Circuit(完整Tor链路)。

(2)Bob利用OP生成一个隐藏服务描述符(HS Descriptor),并生成对应的两个不同的HS Descriptor ID来决定在哪些隐藏服务目录服务器(Hidden Services Directories, 简称HSDirs)上存储生成的HS DescriptorHS Descriptor包含了HS Descriptor ID、介绍节点列表、HS的公钥以及签名等信息。

隐藏服务目录服务器就是拥有HSDir flag的Tor中继。目前猜测获得此flag的条件是该中继同时拥有stable和fast的flag且已运行超过96小时(也有论文提及为25小时),但我的实验中并未证实此条件。

1.2 Client

(1)用户Alice想要访问某暗网,首先需要得知其公布的暗网地址,这里假设为“a.onion”,此处的a就是上文所说的base32编码后的16个字符。通过将其base32解码后得到相应的HS Descriptor ID,并计算出可能存储该HS DescriptorHSDirs。然后通过请求HSDirs直到获得相应的HS Descriptor

问题:此处如何计算出距离最近的一组HSDirs尚未求证,涉及DHT知识。

(2)Alice将认证HS Descriptor的合法性(通过验证HS的签名、时间戳等方式)。认证通过后,Alice的OP会随机选取一个Tor中继,并将其作为与暗网通信中的约会节点(Rendezvous Point,简称RP),该过程通过建立一条Tor链路并发送一个RELAY_COMMAND_ESTABLISH_RENDEZVOUS包来实现。该cell还包含一个Rendezvous cookie(简称RC),RC是一个任意20-bytes的值。

若链路建立成功,RP会返回一个RELAY_COMMAND_RENDEZVOUS_ESTABLISHED包。

一个RC值仅对应一条链路,并且仅用于同RP通信的链路中的认证。

(3)Alice建立一条Tor链路到Bob的一个IP节点,并向其发送一个RELAY_COMMAND_INTRODUCE1cell包,该cell包的payload部分用HS的公钥加密,其主要包含以下部分:

  • RP的IP地址以及fingerprint
  • HS公钥的哈希值
  • Rendezvous Cookie
  • Diffie-Hellman密钥交换的部分($g^x$)
问题:是Alice建立的RELAY_COMMAND_INTRODUCE1包用HS的公钥进行加密,还是IP建立的RELAY_COMMAND_INTRODUCE2包加密,此处尚未求证。

(4)IP将先前Bob提供的公钥通过哈希计算,并与Alice发来的cell包中的HS公钥哈希值作比较;若一致,则会将cell包的剩余部分打包成RELAY_COMMAND_INTRODUCE2并转发给Bob。然后发送RELAY_COMMAND_INTRODUCE_ACK包给Alice,告知其已通知到相应的隐藏服务。

问题:Bob提供给IP的是公钥还是仅仅是公钥的Hash值

(5)Bob在收到RELAY_COMMAND_INTRODUCE2后,先用其先前生成的HS私钥解密,获得其中RP的信息、RC以及$g^x$。Bob将构建一段完整的三跳链路到RP,并且发送RELAY_COMMAND_RENDEZVOUS1包,其包含如下部分:

  • Rendezvous Cookie
  • Diffie-Hellman密钥交换第二部分($g^y$)
  • handshake digest(我猜测是Diffie-Hellman生成的密钥的hash值,即($H(K=g^xg^y)$),用于建立SSL通信)

(6)RP收到包后会校验RC是否与Alice提供的一致;若一致,则将剩下的部分(去除了RC)打包成RELAY_COMMAND_RENDEZVOUS2发送给Alice

(6)Alice收到包后,同时也利用g^x和g^y生成密钥K并哈希,然后与收到的handshake digest比对;若校验一致则SSL握手成功,可以通过RP作为中继节点的两段链路与隐藏服务进行通信。

具体的暗网网络拓扑图如下:

暗网网络拓扑图

2. HS中Descriptor ID和fingerprint之间的联系

从上文得知Descriptor_ID的计算公式如下:

$$Descriptor\_ID=SHA1(asn.1\_public\_key\_id || sercet\_id\_part)$$

此处的secret_id_part计算公式如下:

$$sercet\_id\_part=SHA1(descriptor\_cookie || time\_period ||replica\_index)$$

descriptor_cookie是一个可选参数,如果提供则代表没有认证的用户无法访问该HS,而replica_index是用来创建两个不同的Descriptor_ID


暗网地址的计算公式如下:

$$onion\_address = Base32\big({Descriptor\_ID \over 2}\big)$$

其中"Descriptor_ID / 2"表示截取前半部分,即80bit(SHA1输出160bit的字符串)

下面先简述base32的编码原理,就会发现Tor Hidden Service设计得相当精确。


Base32使用32个字符的集合,其中包括26个大写字母A–Z和数字2–7。

Base32将任意字符串按照字节进行划分,将每个字节对应的二进制值(不足8bit在高位补0)串起来,并按照每组5bit进行切分(所以如果不为5的倍数会在末尾补0),并将切分后的二进制按照Base32编码表进行转换成对应的可打印字符。

由于数据的二进制传输是按照8比特一组进行(即一个字节),因此Base32按5比特切分的二进制数据必须是40比特的倍数(5和8的最小公倍数)。

Base32编码表

下面举例,假设需要编码的字符串为11

(1)1通过ASCII表转换为二进制为00110001,所以字串1100110001 00110001

(2)每5个bit一组进行分组,尾部不足5bit用0补上,故得到00110 00100 11000 10000,通过编码表即为GEYQ

(3)由于要成为40bit的倍数,所以后面还需要20bit的填充位(就是=),也就是还需要填充4组=

(4)所以编码后的结果为GEYQ====


我们会发现,v2协议的暗网地址中从来不会出现=号,就是因为每次截取前半段用于base32编码的二进制串正好是40的倍数!(160bit/2=80bit)

而且80bit编码后,5个bit一组,一共是16个可打印字符,也正好印证了v2协议的暗网地址16个字符位的事实。

fingerprint的计算公式如下:

$$fingerprint=Base16\big(SHA1(asn.1\_public\_key)\big)$$

此处的Base16可以理解为转化为16进制,不过是将字符串中每个字符的二进制拼接起来然后每4位16进制化。

比如11的二进制串为0011000100110001,通过4位一组划分,最后16进制化就是3131

此处将PK通过SHA1哈希化得到的是160bit的串,所以最后得到的就是40位的可打印字符,如708A968F3644F8A547156368FEA3DB664110E631

所以暗网的Descriptor ID和Tor节点的fingerprint其实有着很相似的联系,虽然他们的表现形式不同,这可以为研究暗网中DHT存储descriptor到哪个HSDir节点,以及DHT查询中获取距离最近的可能存储有descriptor的节点集合提供参考。