云樾
踏浪而来
云樾

Tor隐藏服务v3协议规范 - 引入协议部分

本文承接下文:

3. 引入协议

引入协议分为三个步骤。

  1. 首先,一个隐藏服务主机构建到一个Tor节点的匿名链路,并将该链路注册为引入点。若隐藏服务为Single Onion Services(单隐藏服务),则尝试建立非匿名的单跳链路,但在以下情况下使用匿名3跳链路:
    • 引入点位于通过直接连接配置为无法访问的地址上。
    • 通过单跳链路连接到引入点的初始尝试失败,并且他们正在重试引入点连接。
  2. 客户端建立一个到引入点的匿名链路,并发送一个引入请求。
  3. 引入点沿着引入链路将引入请求中继到隐藏服务,并向客户端确认引入请求。

3.1 注册引入点 [REG_INTRO_POINT]

3.1.1 可扩展的ESTABLISH_INTRO协议 [EST_INTRO]

当隐藏服务正在请求新的引入点时,发送具有以下内容的ESTABLISH_INTRO单元:

AUTH_KEY_TYPE [1 byte]
AUTH_KEY_LEN [2 bytes]
AUTH_KEY [AUTH_KEY_LEN bytes]
N_EXTENSIONS [1 byte]
N_EXTENSIONS times:
    EXT_FIELD_TYPE [1 byte]
    EXT_FIELD_LEN [1 byte]
    EXT_FIELD [EXT_FIELD_LEN bytes]
HANDSHAKE_AUTH [MAC_LEN bytes]
SIG_LEN [2 bytes]
SIG [SIG_LEN bytes]

AUTH_KEY_TYPE字段指示引入点身份验证密钥的类型以及在HANDSHAKE_AUTH中使用的MAC的类型。 可识别的类型包括:

[00, 01] -- 保留给保留给旧的介绍单元; 参见下面的[LEGACY_EST_INTRO]
[02] -- Ed25519; SHA3-256.

AUTH_KEY_LEN字段确定AUTH_KEY字段的长度。 AUTH_KEY字段包含公共介绍点身份验证密钥。

EXT_FIELD_TYPE,EXT_FIELD_LEN,EXT_FIELD条目保留用于将来对引入协议的扩展。 必须忽略具有无法识别的EXT_FIELD_TYPE值的扩展名。

HANDSHAKE_AUTH字段包含单元中所有先前字段的消息认证码,使用在链路扩展协议期间生成的共享链路材料(“KH”)作为其密钥,请参阅tor-spec.txt的第5.2节“Setting circuit keys”。 它可以防止ESTABLISH_INTRO单元的重放攻击。

SIG_LEN是签名的长度。

SIG是使用AUTH_KEY对单元中所有内容(不包括SIG)的签名。 这些内容以字符串“ Tor establish-intro cell v1”为前缀。

收到ESTABLISH_INTRO单元后,Tor节点首先对密钥和签名进行解码,并检查签名的有效性。 在下列情况中,该节点必须拒绝ESTABLISH_INTRO单元并销毁链路:

  • 如果密钥类型无法识别
  • 如果密钥格式错误
  • 如果签名不正确
  • 如果HANDSHAKE_AUTH值不正确
  • 如果链路已经是会合链路。
  • 如果链路已经是引入链路。
  • 如果该密钥已经被其他链路使用。

否则,节点必须将密钥与链路相关联,以供以后在INTRODUCE1单元中使用。

3.1.1.1 拒绝服务防御扩展 [EST_INTRO_DOS_EXT]

此扩展可用于将拒绝服务(DoS)参数发送到引入点,以便将其应用于引入电路。

如果使用,则需要在上一节中定义的ESTABLISH_INTRO单元的N_EXTENSIONS字段中进行编码。 内容定义如下:

1. EXT_FIELD_TYPE:

[01] — 拒绝服务参数

如果设置了此标志,则引入点应使用此扩展来了解拒绝服务子系统应该使用的值。

2. EXT_FIELD字段的内容格式为:

N_PARAMS [1 byte] 
N_PARAMS times 
    PARAM_TYPE [1 byte] 
    PARAM_VALUE [8 byte]

其中PARAM_TYPE可能的值为:

[01] — DOS_INTRODUCE2_RATE_PER_SEC

每秒中继到隐藏服务的INTRODUCE2单元的速率。

[02] — DOS_INTRODUCE2_BURST_PER_SEC

每秒中继到隐藏服务的INTRODUCE2信元突发速率。

PARAM_VALUE的大小为8个字节,以适应64位值。 它必须匹配以下PARAM_TYPE的指定限制:

[01] — Min: 0, Max: 2147483647
[02] — Min: 0, Max: 2147483647

值为0表示防御已禁用。 如果将每秒速率设置为0(参数0x01),则应忽略突发速率。 反之亦然,如果突发值为0(参数0x02),则应忽略速率值。 换句话说,将单个参数设置为0都将禁用DoS防御。

每秒突发值不能小于速率值。 如果产生这种设置,则引入点将忽略这些参数。

任何有效值的优先级都高于网络范围内的共识参数。

使用此扩展可以将ESTABLISH_INTRO单元的有效载荷部分扩展19个字节,从而将其从134个字节扩展到155个字节。

该扩展只能用于支持协议版本“HSIntro=5”的洋葱路由。(从tor-0.4.2.1-alpha开始引入)

3.1.2 在旧版Tor节点上注册引入点 [LEGACY_EST_INTRO]

Tor节点还应支持较旧版本的ESTABLISH_INTRO单元,该单元首先在“rend-spec.txt”中进行了说明。 当在不支持[EST_INTRO]中上述格式的较旧的Tor节点上建立引入点时,新的隐藏服务主机必须使用此格式。

在此旧协议中,ESTABLISH_INTRO单元包含:

KEY_LEN        [2 bytes]
KEY            [KEY_LEN bytes]
HANDSHAKE_AUTH [20 bytes]
SIG            [variable, up to end of relay payload]

KEY_LEN变量确定KEY字段的长度。

KEY字段是ASN1编码的旧版RSA公钥,也包含在隐藏服务描述符中。

HANDSHAKE_AUTH字段包含(KH |“ INTRODUCE”)的SHA1摘要。

SIG字段包含使用PKCS1填充的所有早期字段的RSA签名。

Tor的旧版本总是使用1024位RSA密钥作为这些引入身份验证密钥。

3.1.3 确认建立引入点

设置引入链路后,引入点将使用INTRO_ESTABLISHED单元将其状态报告回隐藏服务端。

INTRO_ESTABLISHED单元具有以下内容:

N_EXTENSIONS [1 byte]
N_EXTENSIONS times:
    EXT_FIELD_TYPE [1 byte]
    EXT_FIELD_LEN  [1 byte]
    EXT_FIELD      [EXT_FIELD_LEN bytes]

旧版洋葱路由会发回一个空的INTRO_ESTABLISHED单元格。 服务必须从旧版中继继接受一个空的INTRO_ESTABLISHED单元。

3.2 将一个INTRODUCE1单元发送到引入点 [SEND_INTRO1]

为了参与引入协议,客户端必须了解以下内容:

  • 服务的介绍点。
  • 该介绍点的引入认证密钥。
  • 该介绍点的引入加密密钥。

客户端将INTRODUCE1单元发送到引入点,其中包含隐藏服务的标识符、客户端打算使用的加密密钥的标识符以及要中继到隐藏服务端的不透明的Blob对象。

作为回复,引入点将INTRODUCE_ACK单元发送回客户端,通知客户端其请求已被传递,或者其请求已失败。

3.2.1 INTRODUCE1数据单元格式 [FMT_INTRO1]

当客户端连接到引入节点时,INTRODUCE1单元格应采用以下形式:

LEGACY_KEY_ID   [20 bytes]
AUTH_KEY_TYPE   [1 byte]
AUTH_KEY_LEN    [2 bytes]
AUTH_KEY        [AUTH_KEY_LEN bytes]
N_EXTENSIONS    [1 byte]
N_EXTENSIONS times:
    EXT_FIELD_TYPE [1 byte]
    EXT_FIELD_LEN  [1 byte]
    EXT_FIELD      [EXT_FIELD_LEN bytes]
ENCRYPTED        [Up to end of relay payload]

AUTH_KEY_TYPE如[EST_INTRO]中所定义。 当前,此单元格唯一的AUTH_KEY_TYPE值是Ed25519公钥[02]

LEGACY_KEY_ID字段用于区分旧式和新型的INTRODUCE1单元。在新型INTRODUCE1单元中,LEGACY_KEY_ID为20个0字节。收到INTRODUCE1单元后,引入点将检查LEGACY_KEY_ID字段。如果LEGACY_KEY_ID不为零,则引入点应将INTRODUCE1单元作为旧版INTRODUCE1单元进行处理。

在接收到一个INTRODUCE1单元后,引入点检查AUTH_KEY是否与有效引入链路的引入点验证密钥匹配。 如果是这样,则引入点将具有完全相同内容的INTRODUCE2单元发送到隐藏服务,并向客户端发送一个INTRODUCE_ACK单元作为响应。

3.2.2 INTRODUCE_ACK数据单元格式 [INTRODUCE_ACK]

INTRODUCE_AC数据单元的格式如下:

STATUS       [2 bytes]
N_EXTENSIONS [1 bytes]
N_EXTENSIONS times:
    EXT_FIELD_TYPE [1 byte]
    EXT_FIELD_LEN  [1 byte]
    EXT_FIELD      [EXT_FIELD_LEN bytes]

STATUS字段有以下几种选项:

  • [00 00] — 成功:单元成功中继到隐藏服务主机。
  • [00 01] — 失败:无法识别隐藏服务ID
  • [00 02] — 错误消息格式
  • [00 03] — 无法将数据单元中继到隐藏服务主机

3.3 隐藏服务端处理INTRODUCE2单元 [PROCESS_INTRO2]

收到INTRODUCE2单元后,隐藏服务端将检查AUTH_KEY或LEGACY_KEY_ID字段是否与此引入链路的密钥匹配。

然后,隐藏服务端检查它之前是否已收到包含这些内容的单元格或会合cookie。 如果有,它将以静默方式将其丢弃(新来的这个)。(它必须保持重放缓存,直到它接受具有相同加密密钥的数据单元。注意,下面的加密格式应该是不可扩展的。)

如果该单元不是重复单元,则隐藏服务端将解密ENCRYPTED字段,与客户端建立共享密钥,并将验证单元的全部内容的完整性且未被篡改。根据所选择的加密密钥类型,可能有多种解密ENCRYPTED字段的方法。引入握手协议的要求在[INTRO-HANDSHAKE-REQS]中进行了描述。 我们在下面的[NTOR-WITH-EXTRA-DATA]节中指定一个。

解密后的明文应包含如下格式:

RENDEZVOUS_COOKIE                          [20 bytes]
N_EXTENSIONS                               [1 byte]
N_EXTENSIONS times:
    EXT_FIELD_TYPE                         [1 byte]
    EXT_FIELD_LEN                          [1 byte]
    EXT_FIELD                              [EXT_FIELD_LEN bytes]
ONION_KEY_TYPE                             [1 bytes]
ONION_KEY_LEN                              [2 bytes]
ONION_KEY                                  [ONION_KEY_LEN bytes]
NSPEC      (Number of link specifiers)     [1 byte]
NSPEC times:
    LSTYPE (Link specifier type)           [1 byte]
    LSLEN  (Link specifier length)         [1 byte]
    LSPEC  (Link specifier)                [LSLEN bytes]
PAD        (optional padding)              [up to end of plaintext]

在处理此明文后,隐藏服务将确保扩展字段中存在任何所需的身份验证,然后使用ONION_KEY完成扩展,将会合链路扩展到LSPEC字段中描述的节点。如[BUILDING-BLOCKS]中所述,“TLS-over-TCP,IPv4”和“Legacy node identity”说明符必须存在。

从0.4.1.1-alpha开始,客户端在INTRODUCE1单元中同时包括IPv4和IPv6链接说明符。不论客户端实际用来扩展到会合点的地址如何,所有(会合点的)可用地址都应包含在单元中。

隐藏服务应以与第2.5.2.2节中的客户端相同的方式处理无效或无法识别的链接说明符。但特殊的一点是,隐藏服务可以对链接说明符执行基本的有效性检查,并且不应该拒绝无法识别的链接说明符,以避免信息泄漏。

ONION_KEY_TYPE字段的可选值:
[01] NTOR: ONION_KEY长度为32个字节。

ONION_KEY字段描述了扩展到会合点时所必须使用的洋葱密钥。它必须是隐藏服务描述符中列出的受支持的类型。

使用旧版引入节点时,必须使用加密部分中的PAD字段将INTRODUCE单元填充到特定长度。

收到格式正确的INTRODUCE2单元后,隐藏服务端将持有:

  • 连接到客户选择的会合点所需要的信息。
  • 握手协议的后半部分,用于与客户端进行身份验证并建立共享密钥。
  • 一组用于端到端加密的共享密钥。

3.3.1 引入握手协议加密要求 [INTRO-HANDSHAKE-REQS]

对INTRODUCE2单元中加密信息进行解码时,隐藏的服务主机必须能够:

  • 解密包含在INTRODUCE2单元中的附加信息,包含集合令牌(cookie)和扩展到集合点所需的信息。
  • 建立一组与客户端一起使用的共享密钥。
  • 验证自客户端生成该单元后,其是否未被篡改。

请注意,以前的隐藏服务中设计的旧TAP派生协议实现了前两个要求,但没有实现第三个要求。

3.3.2 握手协议加密示例:具有额外数​​据的ntor [NTOR-WITH-EXTRA-DATA]

这是ntor握手的一种变体(请参阅tor-spec.txt,第5.1.4节;请参阅建议216;并请参阅Goldberg,Stebila和Ustaoglu的“Anonymity and one-way authentication in key-exchange protocols”)。

它的行为与ntor握手相同,不同之处在于,除了协商前向安全密钥外,它还提供了一种加密非前向安全数据到服务器(在本例中,加密到隐藏服务端)的方法, 作为握手的一部分。

此处的表示法与tor-spec.txt的5.1.4节中的定义一样,它定义了ntor握手。

此变体的PROTOID为“tor-hs-ntor-curve25519-sha3-256-1”。 我们还使用以下调整值:

t_hsenc    = PROTOID | ":hs_key_extract"
t_hsverify = PROTOID | ":hs_verify"
t_hsmac    = PROTOID | ":hs_mac"
m_hsexpand = PROTOID | ":hs_key_expand"

为了创建一个INTRODUCE1单元,客户端必须知道此引入链路上用于隐藏服务的公共加密密钥B。 客户端生成一次性密钥对:

x,X=keygen()

并计算:

intro_secret_hs_input = EXP(B,x) | AUTH_KEY | X | B | PROTOID
info = m_hsexpand | subcredential
hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN)
ENC_KEY = hs_keys[0:S_KEY_LEN]
MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN]

并作为INTRODUCE1单元格的ENCRYPTED部分发送:

CLIENT_PK                [PK_PUBKEY_LEN bytes]
ENCRYPTED_DATA           [Padded to length of plaintext]
MAC                      [MAC_LEN bytes]

将这些字段替换为上面[FMT_INTRO1]中描述的INTRODUCE1单元体格式,我们得到:

(此格式如上面的[FMT_INTRO1]中所述,但这里我们描述了如何构建ENCRYPTED部分。)
---------------------------------------------------------------
LEGACY_KEY_ID               [20 bytes]
AUTH_KEY_TYPE               [1 byte]
AUTH_KEY_LEN                [2 bytes]
AUTH_KEY                    [AUTH_KEY_LEN bytes]
N_EXTENSIONS                [1 bytes]
N_EXTENSIONS times:
    EXT_FIELD_TYPE           [1 byte]
    EXT_FIELD_LEN            [1 byte]
    EXT_FIELD                [EXT_FIELD_LEN bytes]
ENCRYPTED:
    CLIENT_PK                [PK_PUBKEY_LEN bytes]
    ENCRYPTED_DATA           [Padded to length of plaintext]
    MAC                      [MAC_LEN bytes]

这里,加密密钥在常规ntor握手中扮演B的角色,而AUTH_KEY字段扮演节点ID的角色。CLIENT_PK字段是公钥X。ENCRYPTED_DATA字段是消息明文,使用对称密钥ENC_KEY加密。MAC字段是从AUTH_KEY到ENCRYPTED_DATA末尾的所有单元的消息认证码,并使用MAC_KEY值作为密钥。

为了处理这种格式,隐藏服务根据需要检查PK_VALID(CLIENT_PK),然后像上面的客户端一样计算ENC_KEY和MAC_KEY,除了在计算intro_secret_hs_input时使用EXP(CLIENT_PK,b)之外。然后,隐藏服务检查MAC是否正确。 如果不正确,则删除该单元。若正确,则它将通过解密ENCRYPTED_DATA来计算纯文本。

现在,隐藏服务端使用已修改的PROTOID来完成tor-spec.txt第5.1.4节中所述的服务端侧的扩展ntor握手协议。明确地说,隐藏服务端生成y,Y = KEYGEN()的密钥对,并使用其引入点加密密钥’b’进行计算:

intro_secret_hs_input = EXP(X,b) | AUTH_KEY | X | B | PROTOID
info = m_hsexpand | subcredential
hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN)
HS_DEC_KEY = hs_keys[0:S_KEY_LEN]
HS_MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN]

(以上用于检查MAC,然后解密加密的数据。)

 rend_secret_hs_input = EXP(X,y) | EXP(X,b) | AUTH_KEY | B | X | Y | PROTOID
NTOR_KEY_SEED = MAC(rend_secret_hs_input, t_hsenc)
verify = MAC(rend_secret_hs_input, t_hsverify)
auth_input = verify | AUTH_KEY | B | Y | X | PROTOID | "Server"
AUTH_INPUT_MAC = MAC(auth_input, t_hsmac)

(以上用于完成ntor握手。)

服务端的握手协议回复如下:

SERVER_PK   Y                         [PK_PUBKEY_LEN bytes]
AUTH        AUTH_INPUT_MAC            [MAC_LEN bytes]

上面这些字段将使用HANDSHAKE_INFO元素在RENDEZVOUS1单元中发送到客户端(请参见[JOIN_REND])。

隐藏服务端现在还知道握手协议生成的密钥,它将使用这些密钥对客户端和服务器之间的数据进行端到端的加密和身份验证。这些密钥的计算详见tor-spec.txt中的5.1.4节。

3.4 在引入阶段进行身份验证 [INTRO-AUTH]

隐藏服务可能仅允许得到授权的用户访问。这样做的一种机制是凭证机制,只有知道隐藏服务凭证的用户才能连接。

3.4.1 基于Ed25519的身份验证

要使用Ed25519私钥进行身份验证,用户必须在INTRODUCE1单元的加密部分包含一个类型为[02]扩展字段EXT_FIELD_TYPE,其内容如下:

Nonce     [16 bytes]
Pubkey    [32 bytes]
Signature [64 bytes]

Nonce是一个随机值。Pubkey是将用于身份验证的公钥。[TODO:这应该是公钥的标识符吗?]签名是使用Ed25519对以下内容进行签名:

 "hidserv-userauth-ed25519"
Nonce       (same as above)
Pubkey      (same as above)
AUTH_KEY    (As in the INTRODUCE1 cell)

隐藏服务端通过查看它是否识别并接受来自所提供公钥的签名来检查这一点。如果是,则检查签名是否正确。若正确,则用户已通过身份验证。

对整个单元的重放预防足以防止对身份验证的重放。

用户不应该对多个隐藏服务使用同一公钥。

声明:转载文章《Tor隐藏服务v3协议规范 - 引入协议部分》请务必注明出处,谢谢
# # #
首页      安全      Tor隐藏服务v3协议规范 - 引入协议部分

发表评论

textsms
account_circle
email

云樾

Tor隐藏服务v3协议规范 - 引入协议部分
阐述Tor-v3隐藏服务中引入协议部分的核心原理
扫描二维码继续阅读
2021-01-27