Umbral:新型分散式密钥管理系统的代理重加密方案

 

前言

现在,我们非常高兴地宣布,我们在定义( https://github.com/nucypher/umbral-doc/blob/master/umbral-doc.pdf )和实现( https://github.com/nucypher/pyUmbral )Umbral的过程中已经到达了一个重要的里程碑。Umbral是一个门限代理(Threshold Proxy)重加密方案,可以在NuCypher KMS( https://blog.nucypher.com/nucypher-kms-decentralized-key-management-system-7783cdaad39e )中实现。
Umbral允许经安全授权的解密权限,可以在任意数量的公共网络参与者之间实现私人的数据共享。这一过程是在不向中间实体透露加密密钥的前提下实现的。
Umbral的特性在于其分裂密钥机制,由于它采用传统的代理重加密方案,所以重加密过程是通过一组节点进行的,而不仅仅是通过单个节点进行分配。
为了进行上述任务,Umbral需要指定一个人数,作为允许进行重加密操作的最少节点数量。这样一来,凭据就会在这些节点之中被拆分,非常类似于Shamir秘密共享的原理,只不过重加密的密钥是其中的一部分,而不是共享的私钥。
“Umbral”这个名字源于西班牙语的“门槛”一词,强调了该方案的分裂密钥特性,该特性在NuCypher KMS的分布式架构中发挥了核心作用。
我们的密码系统是以Python语言实现的,称为pyUmbral( https://github.com/nucypher/pyUmbral )。它使用Cryptography.io( http://cryptography.io/ )和OpenSSL( https://www.openssl.org/ )构建,是一款开源的即用型代理重新加密工具包。

 

关于代理重加密

代理重加密(PRE,https://blog.nucypher.com/proxy-re-encryption-playground-in-python-3bc66170b9bf)是一组算法,它允许半可信代理将密文从一个加密转换到另一个加密,而无需接触到底层明文的任何内容。为此,Alice(原始数据拥有者)创建了一个称为“重加密密钥”的特殊密钥,允许代理转换密文,从而使Bob可以在被称为“重加密”的过程中打开它们。
代理重加密非常适合用于在要与多方共享加密的数据使用场景( https://www.nics.uma.es/pub/papers/nunez2017proxy.pdf ),就不需要再与收件人共享私有的密钥,也不需要为每个收件人都加密整个消息后再进行代理。该加密让用户仅需要进行一次加密操作,随后可以根据收件人的公钥对其进行授权。这样一来,就不必要求所有数据所有者都同时在线,并且还可以轻松撤消某人的访问权限,也可以根据指定的条件来管理访问(例如,限制访问时间)。

Umbral:一种新的代理重加密方案

借助于Umbral,Alice(数据拥有者)可以通过由一组N个半可信代理执行的重新加密过程,将解密的权限授权给Bob(在NuCypher KMS的术语中,称为“Ursulas”)。当这些代理(至少为M个,至多为N个)通过执行重加密操作参与进来时,Bob能够使用自己的私钥解密出原始邮件。Umbral是门限密码系统(Threshold Cryptosystem)的一种,因为重新加密过程必须要N个Ursula中的M个参与其中。
根据另一个技术说明中所述,Umbral受到了ECIES( https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme )和BBS98( https://link.springer.com/chapter/10.1007/BFb0054122 )代理重加密方案的启发,并且进行了一些改进。其中包括,使用了非交互式零知识(NIZK)证明来验证重加密的正确性,以确保KMS节点不会进行欺骗。Umbral的门限功能使用了Shamir秘密共享的思路,让重加密过程成为一个分布式的过程。
在技术文档中,可以查阅更详细的Umbral规范。

pyUmbral

如果没有进行适当的实例化,那么我们的密码系统就不会那么有价值了。pyUmbral是我们第一个Umbral的具体实现,它使用Python编写,并且开源。其加密使用了椭圆曲线密码学算法(特别是曲线secp256k1)和ChaCha20+Poly1305作为认证加密的原语,全部由Cryptography.io的OpenSSL绑定提供。从另一个方面看,pyUmbral不仅是Umbral的一个实现,还未执行基本椭圆曲线运算提供了一个非常出色且简单的框架,也促进了其他基于ECC密码系统的原型设计。
使用pyUmbral的方法非常简单,只需要几步,首先为Alice和Bob创建密钥:

from umbral import pre, keys

# Generate umbral keys for Alice.
alices_private_key = keys.UmbralPrivateKey.gen_key()
alices_public_key = alices_private_key.get_pubkey()
# Generate umbral keys for Bob.
bobs_private_key = keys.UmbralPrivateKey.gen_key()
bobs_public_key = bobs_private_key.get_pubkey()

现在,任何知道Alice公钥的人都可以为她加密一条消息,就像典型的公钥加密过程一样,她可以使用她的私钥对其进行解密:

# Encrypt data with Alice's public key.
plaintext = b'Proxy Re-encryption is cool!'
ciphertext, capsule = pre.encrypt(alices_public_key, plaintext)

# Decrypt data with Alice's private key.
cleartext = pre.decrypt(capsule, alices_private_key,
                        ciphertext, alices_public_key)

请注意,加密的结果是生成一个密文和一个胶囊(Capsule)。使用Umbral,批量的数据会通过新密钥的对称密码进行加密,从而产生密文,而胶囊中则包含了在解密期间重新生成新密钥的必要信息,前提是需要提供有效的私钥。对于有兴趣的读者来说,这是一个典型的关键封装机制。
到目前为止,我们还没有看到代理重加密的过程。我们首先生成一组名为“kfrags”的重加密密钥片段,它们允许将密文的解密权限由Alice分配给Bob。由于Umbral是一个门限密码系统,所以我们需要指定分片总数(N)和所需门限(M)。

# Alice generates split re-encryption keys for Bob with "M of N".
kfrags = pre.split_rekey(alices_private_key, bobs_public_key, 10, 20)

在NuCypher KMS网络中,kfrags将被分配到网络的节点之中,因此Bob不得不与几个Ursulas进行通信,才可以获得整个重加密。在本文的例子中,我们将在本地进行简单的重加密:

# Ursula re-encrypts the capsule to obtain a cfrag.
# Bob attaches the cfrags to the capsule.
for kfrag in kfrags:
    cfrag = pre.reencrypt(kfrag, capsule)
capsule.attach_cfrag(cfrag)

最终,Bob只需要用他的私钥解密结果:

# Bob activates and opens the capsule.
cleartext = pre.decrypt(capsule, bobs_private_key,
                        ciphertext, alices_public_key)

下面是一个关于pyUmbral的演示视频:
https://youtu.be/M8IZ1MTOd24

 

参考资料

PyUmbral实现参考:https://github.com/nucypher/pyUmbral
Umbral技术文档:https://github.com/nucypher/umbral-doc/blob/master/umbral-doc.pdf
如果有任何问题,请通过Discord频道与我们取得联系:https://discord.gg/7rmXa3S

(完)