时间锁加密——藏在未来的钥匙

3203 字
16 分钟
时间锁加密——藏在未来的钥匙

前言#

你是否思考,如何加密一个数据,直到数年之后,才能被未来的某个人解开?

其实,这正是密码学中称为时间锁加密(Timelock Encryption)的问题。

这种加密的实现主要有两种技术途径:

第一种是基于计算复杂度的。这种方法是最经典的方法,由Rivest等人在1996年提出。这种方法不依赖第三方,而是通过问题的计算复杂度来限制解密信息的时间。加密者可以通过其知道(生成)的秘密快速地生成一个谜题。而解密者不知道这个秘密,只能通过执行大量无法并行加速、必须串行执行的计算来暴力解决谜题。这种方法依赖于计算的难度。但是由于计算机的高速发展,可能并不可靠,有被提前解密的风险。最著名的是Rivest的LCS35实验,在1999年设计的谜题,按照当时计算机水平需要连续计算35年(直到2033年),然而,这个问题却在2019年被一位名叫Bernard Fabrot的程序员,使用更高效的算法和普通台式机,只耗时3年零3个月独立完成了解答。并且,即使忽略计算机性能的变化,这种方法需要连续的复杂运算,对于一般人来说解密成本极高。实用价值很有限。

另一种是基于权威网络的。这是一种更新的实现方式,利用去中心化的网络来“发布”解密密钥。这种方法无需大量计算,效率更高。安全性由整个网络保证,对于一般人来说已经足够安全。本文将主要介绍这种方式。

drand与tlock的简介#

drand#

drand是一个由全球多个组织(Cloudflare等)共同维护的分布式随机数生成网络,提供了一个公开、可验证、无偏且不可预测的随机数来源。

drand网络中的节点之间通过特定的算法,每隔固定时间(3秒)生成一个随机数。它采用阈值BLS签名技术,这意味着只要有超过设定阈值的节点参与,就能生成并验证随机数,杜绝了单点操纵的可能性。

tlock#

drand
/
tlock
Timelock Encryption made practical. The Go `tlock` library and the `tle` cmd line tool home to encrypt towards the future.
Apache-2.0
Go

tlock是一个利用drand网络实现时间锁加密(Timelock Encryption)的工具。

它基于基于身份的加密(IBE) 技术,数据被加密后,对应的解密密钥在数学上与某个未来轮次的drand随机数绑定。由于任何人都无法预知未来的drand随机数,因此在该轮次到来前,数据无法被解密。只有在该随机数被生成后,才能解密数据。

drand与tlock的一些密码学原理#

作者只是一个普通高中生,对数学的研究有限,此处大量信息由llm总结提炼,可能有错误,欢迎指正。

核心基础:双线性配对#

在普通的椭圆曲线密码学中,我们只能做点的加法点的数乘(即把一个点乘以一个整数)。但双线性配对引入了一种全新的运算:它可以把两个椭圆曲线上的点映射到第三个群里的一个数

简单来说,配对是一个特殊的函数 ee,它接受两个点 PPQQ 作为输入,输出一个数。它有三个关键性质:

  1. 双线性e(aP,bQ)=e(P,Q)abe(aP, bQ) = e(P, Q)^{ab}
  2. 非退化性:结果不会是平凡的(不会全是1)。
  3. 可计算性:存在高效的算法来计算这个配对。

drand使用的是BLS12-381这条椭圆曲线,基于它构建了一个双线性群。具体来说,有三个群 G1\mathbb{G}_1G2\mathbb{G}_2GT\mathbb{G}_T,以及一个配对函数:

e:G1×G2GTe: \mathbb{G}_1 \times \mathbb{G}_2 \rightarrow \mathbb{G}_T

其中 G1\mathbb{G}_1G2\mathbb{G}_2 是椭圆曲线上的点构成的群,GT\mathbb{G}_T 是目标群(一个大整数群)。每个群都有一个生成元,分别记为 g1g_1g2g_2gTg_T

BLS签名#

BLS签名(Boneh-Lynn-Shacham签名)是一种基于双线性配对的数字签名算法。它的最大特点是确定性:同样的消息用同样的私钥签名,结果永远一样。

密钥生成#

签名者随机选择一个私钥 sk=sZpsk = s \in \mathbb{Z}_p^*(即一个小于大素数 pp 的正整数),然后计算公钥:

PK=sg2G2PK = s \cdot g_2 \in \mathbb{G}_2

(意思就是私钥这个数乘以群 G2\mathbb{G}_2 的生成元,得到曲线上的一个点,这个点就是公钥)

签名生成#

要对消息 mm 签名,首先用一个哈希函数 HH 把消息映射到 G1\mathbb{G}_1 群上的一个点:

h=H(m)G1h = H(m) \in \mathbb{G}_1

然后签名就是:

σ=shG1\sigma = s \cdot h \in \mathbb{G}_1

签名就是把私钥乘以哈希点,得到 G1\mathbb{G}_1 上的另一个点。由于这里没有像ECDSA那样需要随机数,所以每次对同一消息签名结果都一样。

签名验证#

验证者拿到签名 σ\sigma、消息 mm 和公钥 PKPK,检查以下等式是否成立:

e(σ,g2)=?e(H(m),PK)e(\sigma, g_2) \stackrel{?}{=} e(H(m), PK)

之所以这个等式应该成立,是因为:

e(σ,g2)=e(sH(m),g2)=e(H(m),g2)s=e(H(m),sg2)=e(H(m),PK)e(\sigma, g_2) = e(s \cdot H(m), g_2) = e(H(m), g_2)^s = e(H(m), s \cdot g_2) = e(H(m), PK)

这里就用到了配对的双线性性质。如果等式成立,说明签名确实是由掌握着私钥 ss 的人生成的。

阈值BLS签名#

drand的是一个去中心化的网络,因此实际上使用的是阈值BLS签名(Threshold BLS signature)。即:有 nn 个节点,只要其中至少 tt 个节点(tt 称为阈值)合作,就能生成一个有效的签名,而少于 tt 个节点则无法做到。

分布式密钥生成(DKG)#

在初始阶段,所有节点需要协作生成一个共享的公钥和各自持有的私钥分片,这个过程叫做分布式密钥生成(Distributed Key Generation, DKG)。

drand使用的是Pedersen的DKG协议。简单来说:

  1. 每个节点 ii 随机选择一个私钥分片 sis_i
  2. 通过Shamir秘密共享(Shamir Secret Sharing),将秘密分散成多个碎片分发给其他节点。
  3. 所有节点协作,最终产生一个集体的私钥 ss(但没有任何一个节点知道完整的 ss),以及对应的集体公钥 S=sg2S = s \cdot g_2

每个节点只持有自己的一份私钥分片 sis_i,无法单独签名。Shamir秘密共享的核心思想是:用一个 t1t-1 次多项式 f(x)f(x) 来编码秘密 s=f(0)s = f(0),每个节点得到 f(i)f(i) 作为分片。任意 tt 个分片可以重构出 ff 从而算出 ss,但少于 tt 个则不行。

阈值签名生成#

每一轮,所有节点对同一个消息 mm(通常是轮次号)进行签名:

  1. 每个节点 ii 计算自己的部分签名σi=siH(m)\sigma_i = s_i \cdot H(m)
  2. 每个节点广播自己的部分签名。
  3. 当收集到至少 tt 个部分签名后,就可以把它们聚合成一个完整的BLS签名:
σ=iTσi=(iTsi)H(m)=sH(m)\sigma = \sum_{i \in T} \sigma_i = \left(\sum_{i \in T} s_i\right) \cdot H(m) = s \cdot H(m)

由于Shamir秘密共享的性质,任意 tt 个分片通过拉格朗日插值可以重构出完整的私钥 ss,所以聚合后的签名就是一个有效的BLS签名。

最终随机数#

drand最终输出的随机数,就是对这个聚合签名 σ\sigma 再做一次哈希:

randomness=SHA256(σ)\text{randomness} = \text{SHA256}(\sigma)

基于身份的加密(IBE)#

基于身份的加密(Identity-Based Encryption, IBE)是一种特殊的公钥加密方案。在传统加密中,公钥是一串数字;但在IBE中,公钥可以是任何字符串——比如用户的邮箱地址、名字,或者像tlock中使用的“轮次号”。

tlock使用的是Boneh-Franklin IBE方案,它同样基于双线性配对。

IBE的系统组成#

一个IBE系统有四个部分:

  1. Setup(系统初始化):一个受信任的私钥生成中心(Private Key Generator, PKG)生成系统主密钥 ss 和系统公开参数。
  2. Extract(私钥提取):PKG根据用户的身份 IDID,计算出对应的私钥并安全地分发给用户。
  3. Encrypt(加密):任何人都可以用用户的身份 IDID 作为公钥来加密消息。
  4. Decrypt(解密):用户用自己的私钥解密。

Boneh-Franklin IBE的数学细节#

系统初始化(Setup)

选择一个双线性群,生成元为 g1G1g_1 \in \mathbb{G}_1。随机选择主密钥 sZps \in \mathbb{Z}_p^*,计算系统公钥:

Ppub=sg1G1P_{pub} = s \cdot g_1 \in \mathbb{G}_1

系统公开参数为 (g1,Ppub)(g_1, P_{pub}),主密钥 ss 由PKG秘密保管。

私钥提取(Extract)

当用户以身份 IDID 请求私钥时,PKG计算:

QID=H(ID)G1Q_{ID} = H(ID) \in \mathbb{G}_1

然后用户的私钥为:

dID=sQIDG1d_{ID} = s \cdot Q_{ID} \in \mathbb{G}_1

加密(Encrypt)

发送者想给身份为 IDID 的用户发送消息 MM。他首先计算:

QID=H(ID)G1Q_{ID} = H(ID) \in \mathbb{G}_1

然后选择一个随机数 rZpr \in \mathbb{Z}_p^*,计算密文:

C=(U,V)=(rg1,  MH2(e(QID,Ppub)r))C = (U, V) = \big(r \cdot g_1,\; M \oplus H_2(e(Q_{ID}, P_{pub})^r)\big)

其中 \oplus 是异或运算,H2H_2 是另一个哈希函数。

解密(Decrypt)

接收者用自己的私钥 dIDd_{ID} 解密密文:

M=VH2(e(dID,U))M = V \oplus H_2(e(d_{ID}, U))

因为:

e(dID,U)=e(sQID,rg1)=e(QID,g1)sr=e(QID,sg1)r=e(QID,Ppub)re(d_{ID}, U) = e(s \cdot Q_{ID}, r \cdot g_1) = e(Q_{ID}, g_1)^{sr} = e(Q_{ID}, s \cdot g_1)^r = e(Q_{ID}, P_{pub})^r

加密和解密时计算的是同一个值,所以异或操作可以完美抵消。

简单理解:IBE的核心思想是,PKG用主密钥 ss 为每个身份生成私钥,而任何人只要知道身份 IDID,就可以用系统公钥 PpubP_{pub} 来加密。配对保证了只有拥有对应私钥的人才能解密。

tlock:将IBE与drand结合#

tlock的核心思想是:把drand网络当作一个去中心化的IBE私钥生成中心(PKG)

在tlock中:

  • 身份(Identity) = 未来的轮次号 pp
  • IBE私钥 = drand在轮次 pp 生成的BLS签名 σp=sH(p)\sigma_p = s \cdot H(p)

因为drand网络本身就是分布式生成BLS签名的,所以它天然可以充当IBE的私钥生成中心——不需要额外的可信第三方。

加密过程(向未来加密)#

假设你想加密消息 MM,让它在第 pp 轮才能被解密:

  1. 获取drand网络的集体公钥 S=sg1G1S = s \cdot g_1 \in \mathbb{G}_1
  2. 计算 PK=e(S,H(p))=e(sg1,H(p))PK = e(S, H(p)) = e(s \cdot g_1, H(p))
  3. 选择一个随机数 rr(或从消息派生出随机数)。
  4. 计算密文:
    • U=rg1U = r \cdot g_1
    • V=nonceH(rPK)V = \text{nonce} \oplus H(r \cdot PK)(nonce是一个随机值)
    • W=MH(nonce)W = M \oplus H(\text{nonce})

最终密文为 (U,V,W)(U, V, W)

这里 PK=e(S,H(p))PK = e(S, H(p)) 就是轮次 pp 对应的IBE公钥,任何人都可以计算。

解密过程(时间到达后)#

当第 pp 轮到来时,drand网络会生成BLS签名 σp=sH(p)\sigma_p = s \cdot H(p)。当这个签名被生成后就可以执行解密:

  1. 计算 nonce=VH(e(U,σp))\text{nonce}' = V \oplus H(e(U, \sigma_p))
  2. 计算 M=WH(nonce)M' = W \oplus H(\text{nonce}')

还是因为同样的等式:

e(U,σp)=e(rg1,sH(p))=e(g1,H(p))rs=e(sg1,H(p))r=e(S,H(p))r=PKre(U, \sigma_p) = e(r \cdot g_1, s \cdot H(p)) = e(g_1, H(p))^{rs} = e(s \cdot g_1, H(p))^r = e(S, H(p))^r = PK^r

所以解密时计算出的 e(U,σp)e(U, \sigma_p) 和加密时使用的 PKrPK^r 是同一个值,异或操作完美抵消,成功解密得到明文。

安全性保证#

tlock的安全性依赖于两个事实:

  1. 没有人能提前知道未来的BLS签名 σp\sigma_p,因为drand的随机数是不可预测的。
  2. 除非你拥有 σp\sigma_p,否则无法解密——这由IBE的安全性保证。

因此,加密的数据在指定时间之前无法被任何人解密

drand与tlock的应用#

通过以上内容我们已经知道,可以利用drand和tlock实现安全且便捷的时间锁加密。下面将介绍这种加密的具体实现。

timelock.dev#

直接访问即可使用。

加密
加密

设置好对应的参数后点击加密,便可得到这样的文本

-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHRsb2NrIDMxOTMxODY3IDUyZGI5YmE3
MGUwY2MwZjZlYWY3ODAzZGQwNzQ0N2ExZjU0Nzc3MzVmZDNmNjYxNzkyYmE5NDYw
MGM4NGU5NzEKbUd4TGpTT2VpVGpoaHdIbGZrMWJ0VmhpbXBjdm1mc1RvT0FhMkdQ
NzhaV2M1Zlo3dmlMRjNoUjkyUk1FSlVGcgpFVkhHT0NpaGY3SnI2UHAwcTdhQy8w
Z0pVTHRHZjc0cHNXZmo1ajUxYkZYalN0bGoyRHlxcTIyWnMwMU1KTkJ0CkpsYWRS
OGZXMzBmUGxSdEJzSG9nSWJTNWc1YnFYeTlEN1ZtdGJoNm5sT0kKLT4gYjBQOEMo
UmYtZ3JlYXNlCmlzUm94SENZNVBwdmVTM05vNHp4K09vaEZnCi0tLSBOZTdVODA3
WVpMZ1VUVHJuRTYrZS9pQlMwQkdya2xSa05uL3J0K3lqK1p3CoqtKsdy9grZ6z7t
JdWJXD6MEwNOfc8Ti4wpyjQCpGUfa7+AYcevHIpb
-----END AGE ENCRYPTED FILE-----

在时间到达之前,如果尝试解密将提示Unable to decrypt. You might need to wait longer. That's all we know.

只有当时间达到,才会解密成功

文本
文本

tle#

通过命令安装tle

Terminal window
go install github.com/drand/tlock/cmd/tle@latest

然后可以使用tle命令进行加解密(默认使用drand mainnet的quicknet)

Terminal window
tle -D 10d -o encrypted_file data_to_encrypt
# 十天后
tle -d -o decrypted_file.txt encrypted_file

参考资料#

drand 文档#

  1. drand 官方文档

  2. drand GitHub 仓库

  3. drand 密码学详解:Cloudflare 文档

tlock 文档#

  1. tlock 论文:详细阐述 tlock 时间锁加密方案的数学原理和安全证明。

  2. drand Timelock Encryption 介绍:drand 官方对 tlock 时间锁加密方案的概述。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
时间锁加密——藏在未来的钥匙
https://blog.00910721.xyz/posts/timelock-encryption/
作者
透明质酸钠
发布于
2026-09-05
许可协议
CC BY-NC 4.0

评论区

Profile Image of the Author
透明质酸钠
宁宁就要0721!
关于网站主题
网站近期修改了主题配置,如果界面还是粉色,请您清空本网站的本地存储~~
分类
标签
最新动态
站点统计
文章
11
分类
7
标签
21
总字数
15,929
运行时长
0
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC 4.0