B32用于加密的LS2

Proposal 149
Closed
Author zzz
Created 2019-03-13
Last Updated 2020-08-05
Target Version 0.9.40
Implemented In 0.9.40

注意

网络部署和测试正在进行中。 可能会有小的修订。 请参阅 SPEC 获取官方规范。

概述

标准Base 32 (“b32”) 地址包含目标的哈希值。 这对于加密的ls2(提案123)不起作用。

您不能为加密的LS2(提案123)使用传统的base 32地址, 因为它仅包含目标的哈希值。它不提供非盲化的公钥。 客户端必须知道目标的公钥、签名类型、 盲化签名类型以及可选的秘密或私钥 才能获取和解密leaseset。 因此,单独的base 32地址是不够的。 客户端需要完整的目标(包含公钥)或仅公钥本身。 如果客户端在地址簿中有完整的目标,并且地址簿 支持按哈希的反向查找,则公钥可以被检索。

因此,我们需要一个新的格式,将公钥而不是哈希放入 base32地址中。此格式还必须包含 公钥的签名类型和盲化方案的签名类型。

本提案记录了这些地址的新b32格式。 虽然我们在讨论中将这种新格式称为“b33”地址, 但实际的新格式保留了通常的“.b32.i2p”后缀。

目标

  • 包含非盲化和盲化签名类型以支持未来的盲化方案
  • 支持大于32字节的公钥
  • 确保b32字符都是或大多数是随机的,尤其是在开头 (不希望所有地址以相同字符开头)
  • 可解析
  • 指示需要盲化秘密和/或每客户端密钥
  • 添加校验和以检测拼写错误
  • 最小化长度,保持DNS标签长度少于63字符用于正常使用
  • 继续使用base 32以实现不区分大小写
  • 保留通常的“.b32.i2p”后缀

非目标

  • 不支持包含盲化秘密和/或每客户端密钥的“私人”链接; 这将是不安全的。

设计

  • 新格式将包含非盲化的公钥,未盲化的签名类型, 和盲化的签名类型。
  • 可选地包含秘密和/或私钥,仅用于私人链接
  • 使用现有的“.b32.i2p”后缀,但长度更长。
  • 添加一个校验和。
  • 加密leasesets的地址由56或更多编码字符 (35或更多解码字节)标识,相对于传统base 32地址的52字符(32字节)。

规范

创建和编码

构造一个主机名为{56+ 字符}.b32.i2p (35+ 字节二进制),如下:

flag (1 byte)
    bit 0: 0 表示一字节签名类型,1 表示两字节签名类型
    bit 1: 0 表示无秘密,1 表示需要秘密
    bit 2: 0 表示无每客户端认证,
           1 表示需要客户端私钥
    bits 7-3: 未使用,设置为0

  public key sigtype (1 or 2 bytes as indicated in flags)
    如果是1字节,上位字节假定为零

  blinded key sigtype (1 or 2 bytes as indicated in flags)
    如果是1字节,上位字节假定为零  

  public key 
    字节数量由签名类型隐含

后处理和校验和:

构造如上的二进制数据。
  将校验和视为小端。
  计算校验和 = CRC-32(data[3:end])
  data[0] ^= (byte) checksum
  data[1] ^= (byte) (checksum >> 8)
  data[2] ^= (byte) (checksum >> 16)

  hostname = Base32.encode(data) || ".b32.i2p"

b32末端的任何未使用位必须为0。 对于标准的56字符(35字节)地址,没有未使用的位。

解码和验证

从主机名中去掉“.b32.i2p”
  data = Base32.decode(hostname)
  计算校验和 = CRC-32(data[3:end])
  将校验和视为小端。
  flags = data[0] ^ (byte) checksum
  如果是1字节签名类型:
    pubkey sigtype = data[1] ^ (byte) (checksum >> 8)
    blinded sigtype = data[2] ^ (byte) (checksum >> 16)
  否则 (2字节签名类型) :
    pubkey sigtype = data[1] ^ ((byte) (checksum >> 8)) || data[2] ^ ((byte) (checksum >> 16))
    blinded sigtype = data[3] || data[4]
  根据flags解析余下内容以获取公钥

秘密和私钥位

秘密和私钥位用于向客户端、代理或其他 客户端代码表明解密leaseset时需要秘密和/或私钥。具体实现可能会提示用户提供 所需数据,或在所需数据缺失时拒绝连接尝试。

正当性

-通过将前3字节与哈希进行XOR操作提供了有限的校验能力, 并确保所有base32字符在开头是随机的。 只有少数标志和签名类型组合是有效的,因此任何拼写错误都可能造成无效组合并将被拒绝。

  • 在通常情况下(1字节签名类型,无秘密,无每客户端认证), 主机名将为{56字字符}.b32.i2p,解码为35字节,与Tor相同。
  • Tor 2字节校验和具有1/64K的错误否定率。通过3字节,减去一些忽略字节, 我们的接近百万分之一,因为大多数标志/签名类型组合是无效的。
  • Adler-32对于小输入和检测小变化选择很差 。 改用CRC-32。CRC-32速度快且被广泛使用。

缓存

尽管不在本提案的范围内,路由器和/或客户端必须记住并缓存 (可能是持久性的)公钥与目标的映射,反之亦然。

说明

  • 通过长度区分新旧口味。旧b32地址始终为{52字字符}.b32.i2p。新地址为{56+字字符}.b32.i2p。
  • Tor讨论线程:https://lists.torproject.org/pipermail/tor-dev/2017-January/011816.html
  • 不要期望2字节签名类型会发生,我们仅到13。现在无需实现。
  • 如果需要,新格式可以像b32一样用于跳转链接(并由跳转服务器提供)。

问题

  • 任何大于32字节的秘密、私钥或公钥将会超过DNS最大标签长度63字符。浏览器可能不在意。

迁移

没有向后兼容的问题。旧软件中长的b32地址将无法转换为32字节的哈希。