密钥管理是密码学应用的核心问题之一。任何涉及加密/签名的应用,无论算法本身机制多么安全,最终都会受到灵魂拷问:你密钥存在哪儿?本文实现了一种安全的密钥管理方案,基于安全多方计算技术,避免了客户端、服务器端内存中的密钥泄露风险,并已经在阿里集团内的密钥管理系统上线。
背景介绍:密钥管理
提问:你密钥存在哪儿?
对这一问的回答基本可概括为2类:
a. 本地加解密:密钥保存在某些介质(如配置文件、数据库,也可以是某个远程服务器)中,用户在需要进行加密/签名时,从这些介质拉取密钥(可能拉取的只是密钥密文,需要再解密出密钥明文),然后本地进行加密/签名。
b. 服务器加解密:用户在需要进行加密/签名时,把数据请求发给某个服务器,服务器代为完成加密/签名工作,将加密/签名结果发回用户。
一般的密钥管理系统都可归到这两类模式,但是他们都存在各自的问题:
1. 前者由于密钥是被拉到了用户本地,暴露在用户内存中,而用户本机的安全性是无法做任何假设的,可能存在各种漏洞/木马等,因此密钥面临着各类泄露风险;在客户端引入 TEE 可以提升这个安全门槛,但是需要配置额外的硬件,而且没有100%杜绝泄露风险(如侧信道等);
2. 后者的密钥是完全交给了服务器,万一服务器存在漏洞/服务器被入侵/服务器管理员作恶,那么用户隐私便在服务器面前一览无余。
可能有些同学觉得这2类风险不够高,但是对于高价值数据,这些风险是不可忽视的。举个例子,假设你是中本聪,那么你的比特币创世块地址对应的私钥放哪才能不忘掉,同时不泄露呢?是不是好像这两种方法都无法满足需求了?
基于安全多方计算的密钥管理(MPC KMS),也称门限签名/门限加密,即是为了解决这一对矛盾。简而言之,MPC KMS 将用户密钥分为 M 份"碎片"(例如 M=2,密钥是100,可以拆成两份30和70),存储在 M 个不同的服务器中(例如一份存在A云服务商,一份存在B云服务商),任何一个服务器都无法独立根据自己的"碎片"恢复出用户密钥原文。当用户需要进行加密/签名时,则在这 M 个服务器之间运行一个 MPC 协议,产生加密/签名的结果,且整个过程中不需要复原用户密钥。
如果最少只需要 n 个服务器参与即可完成协议,则称之为 n of M 的门限签名/加密。
可见,在 MPC KMS 中,上述两种风险均可以得到有效的规避:首先,用户本地环境的安全问题不会导致密钥泄露;其次,即使某个服务器出问题,攻击者也无法得到用户的密钥,必须同时攻陷 n 个服务器,或是 n 个服务器管理员一起合谋(如果我们把服务器部署在多个独立的云服务系统上,这种同时出问题的概率几乎可以忽略)。
MPC KMS 这种去中心化密钥管理的特点和区块链的共识机制具有非常好的兼容性:除了直接用于保管用户私钥、节点密钥之外,用户还可以把私钥托管分成 M 片,托管在区块链的 M 个节点,然后设定仅当满足一定门限的节点(例如1/4的节点)产生共识时才能动用他的某笔数字货币财产;或是设定某个软件包的发布必须经过一定门限的节点签名等等。
安全多方计算 MPC 介绍
安全多方计算( Secure Multi-Party Computation,MPC)在80年代由姚期智院士提出。安全多方计算协议允许多个数据所有者进行数据协同计算,输出计算结果,并保证任何一方均无法得到除应得的计算结果之外的其他任何信息。
这里的黑色加粗字体的文字是格外需要注意的:不仅仅是无法获取原始数据,而是无法获得其他任何信息。以百万富翁问题为例:两个百万富翁比谁的钱数更多,最后双方获得的唯一信息只能是“大于、等于或小于”;只要泄露了任何的其他额外信息(譬如对方钱数的最高位是1还是2),无论这个额外信息多么少,都不能算 MPC。
MPC 还有很多潜在应用场景,如基于融合数据的联合风控、联合广告推荐等,它能够真正实现“数据可用不可见”,在这个数据为王的时代有着美妙的前景。
安全多方计算+密钥管理MPC KMS介绍
技术架构
MPC KMS 即是安全多方计算 MPC 的一种特殊场景:各方分别持有密钥的一部分,协同计算的目的是加解密/签名,同时除了加解密/签名结果之外,不泄露任何其他信息。
我们研读了多篇最新论文[1,2,3],在这些论文的理论基础之上,实现了安全两方 ECDSA 签名系统。系统的粗粒度交互过程如下,详细算法可以参阅论文。
1.密钥生成:用户发起生成请求,两台服务器 A 和 B 分别各自独立的产生随机数 a 和随机数 b,a+b 即是签名时使用的私钥。
2.签名:用户首先从 A 服务器拉取 a,然后调用 B 的服务,把需要签名的消息message 和 message、a 的加密计算结果发送给 B,和 B 之间运行一个安全两方签名协议,得到最终的签名值
。在整个过程中,私钥a+b没有在任何一方的内存中复原,任何一方都无法了解到私钥 a+b 的内容。
操作流程
最终系统暴露给用户的是两个接口 getPK() 和 sign(),接口以阿里内部常用的HSF(High-speed Service Framework) 方式提供,接入非常方便。
Step 1. 用户首先在密钥管理服务器上新建一个密钥,后台的两台服务器会自动的产生各自的密钥分量;
Step 2.用户调用 getPK() 获取该密钥对应的公钥;
Step 3.用户在密钥管理服务器上新建一个 SHA256WithECDSA 类型的公钥,选择手工输入,输入 Step 2得到的内容;
Step 4.用户此后就可以通过 sign() 来调用安全两方签名,通过密钥管理服务器提供的ECDSA verifier 函数,输入公钥来验证签名的正确性了。
Step 5. 这下安全性超有保障,连管理员都得两个服务器的管理员一起码代码才能知道你的私钥到底是啥了!
参考文献:
[1] Lindell Y. Fast secure two-party ECDSA signing[C]//Annual International Cryptology Conference (CRYPTO). Springer, Cham, 2017: 613-644.
[2] Doerner J, Kondi Y, Lee E, et al. Secure Two-party Threshold ECDSA from ECDSA Assumptions[C]//2018 IEEE Symposium on Security and Privacy (SP). IEEE, 2018: 980-997.
[3] Lindell Y, Nof A. Fast secure multiparty ecdsa with practical distributed key generation and applications to cryptocurrency custody[C]//Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security (CCS). ACM, 2018: 1837-1854.
【本文为51CTO专栏作者“阿里巴巴官方技术”原创稿件,转载请联系原作者】