写点什么

隐私 AI 框架中的数据流动与工程实现

  • 2020-11-03
  • 本文字数:6809 字

    阅读完需:约 22 分钟

隐私AI框架中的数据流动与工程实现

上一篇文章中,我们介绍了,对于安全技术开发者,如何快速的基于 Rosetta 等隐私 AI 框架所提供的一系列接口,将自己的安全协议集成落地到上层的 AI 应用中来。在这一篇文章中,我们将介绍为了保护用户的隐私数据,在隐私 AI 框架的计算任务全流程中,数据是如何以密文形式流动,同时仍正确完成加法、乘法等计算步骤的。


隐私 AI 系统存在的目的就是赋能 AI,使得各种 AI 场景下对用户隐私数据的使用都是安全的。那么,这样的系统就需要提供充分的保障,从理论到工程实现的每一个阶段都应该是经得起推敲、抵抗得住各种攻击的。不能简单的认为只需要各方先在本地自己的数据上计算出一个模型,然后将模型结果交换一下计算下其模型参数的平均值,就不会泄露各方的隐私数据了。现代密码学(Cryptography)是建立在严格的数学定义、计算复杂度假设和证明基础之上的,其中 MPC (Multi-Party Computation)方向是专门研究多个参与方如何正确、安全的进行联合计算的子领域, RosettaTF Encrypted 等隐私 AI 框架都采用了 MPC 技术以提供可靠的安全性。下面我们就结合具体案例看的看下在 Rosetta 中隐私数据是如何得到安全保护的。

案例

Alice, Bob 和 Charley 三人最近需要在他们的 AI 系统中引入对数据的隐私保护能力。他们很重视安全性,所以他们想通过一个简单的例子 —— 乘法(multiply),来验证下隐私 AI 框架是否真正做到了隐私安全。


他们约定:Alice 的输入为 1.2345;Bob 的输入为 5.4321;而 Charley 拿到相乘的结果。


他们按照 Rosetta 提供的教程,快速编写了如下代码(脚本名为 rosetta-mul.py):


#!/usr/bin/env python3import latticex.rosetta as rttimport tensorflow as tf
rtt.activate("SecureNN")x = tf.Variable(rtt.private_console_input(0, shape=(1,))) # Alice's inputy = tf.Variable(rtt.private_console_input(1, shape=(1,))) # Bob's inputz = tf.multiply(x, y) # z = x * y
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) res = sess.run(rtt.SecureReveal(z, receive_party=4)) # 'b0100' means Charley print('z:', res)
rtt.deactivate()
复制代码


接着,他们各自打开一个终端,分别进行如下操作:


Alice (P0) 在终端敲下如下命令行,并根据提示输入自己的私有数据:


$ python ./rosetta-mul.py --party_id=0please input the private data (float or integer): 1.2345
复制代码


Bob (P1) 执行同样的操作,输入的也是只有自己才知晓的私有数据:


$ python ./rosetta-mul.py --party_id=1please input the private data (float or integer): 5.4321
复制代码


Charley (P2) 在终端敲下如下命令行,等一会儿就可以得到所期望的计算结果:


$ python ./rosetta-mul.py --party_id=2z: [b'6.705910']
复制代码


注:

  • 对于 Charley 来说,由于没有数据,故不会提示输入。

  • Alice 和 Bob 的本地输出都会是 z: [b'0.000000'], 而不会拿到正确的结果。


可以看出,Charley 拿到的最终结果与逻辑上明文结果(6.70592745)相比,误差(0.00001745)可以忽略不计。系统的正确性得到了验证。


如果想让误差更小,可以通过配置提升精度,或使用 128-bit 的数据类型。具体操作可以参考文档


上面短短的几行代码,虽然结果是正确的,但是他们三人对于系统安全性方面仍有一些困惑:


  • Alice、Bob 的私有输入会不会被另外两方知道?

  • Charley 拿到的结果会不会被 Alice 、 Bob 知道?

  • 整个程序运行过程中,有没有其他数据的泄漏?

  • 如果前几问的回答都是否定的,那 Charley 又是如何得到明文?


在回答这些问题之前,为简化描述、突出本质,我们需要简单介绍一下 MPC 实际落地中常用的安全假设。


假定系统中有 3 个节点,P0/P1/P2,其中 P0/P1 为数据参与方,而P2 是辅助节点,用于随机数生成。


  • 只考虑半诚实(Semi-Honest)安全模型,即三方都会遵守协议执行的流程,并且其中诚实者占多数(Honest-Majority),也就是说三个节点中只会有一个“坏人”。更为复杂的恶意(Malicious)模型等安全场景可参考其他相关论文。

  • 内部数据类型为 64 位无符号整型,即 uint64_t (这在理论上对应着在环 )。


下面我们就按照 输入–计算–输出 的顺序,详细介绍 Rosetta 中数据的表示与流动,以及所用到相关技术与算法在工程上的优化实现。

隐私数据的输入

隐私计算问题,首先要解决的是隐私数据的输入。


在上述案例中,是通过如下两行代码来完成私有数据的安全输入的:


x = tf.Variable(rtt.private_console_input(0, shape=(1,))) # Alice's inputy = tf.Variable(rtt.private_console_input(1, shape=(1,))) # Bob's input
复制代码


如代码所示,rtt.private_console_input 是 Rosetta 众多 API 之一,Rosetta 还提供了 rtt.private_inputrtt.PrivateDataset 等 API,用来处理隐私数据的输入。


这里发生了什么?x,y 的值会是什么?


在进入剖析之前,先来了解一个重要的概念 —— 秘密分享

秘密分享

什么是 秘密分享(Secret Sharing)[1]?先来看一种简单的两方 additive 的构造:


给定一个数 x,定义 share(x) = (x0, x1) = (x − r, r),其中 r 是随机数,并且与 x 独立。可以看到,x = x0 + x1 = x -r + r。原始数据 x 的秘密分享值 (x0, x1) 将会由两个数据参与方 (P0, P1) 各自保存。


在秘密分享的方案中,所有的数据,包括中间数值都会分享在两个参与方之间。直观的看,参与的两方不会得到任何的明文信息。理论上,只需要在环 上支持加法和乘法,就可以进一步通过组合来支持上层各种更复杂的函数。下文我们会看到关于乘法的详细解析,读者可以回过头来再看这段话。


那工程上是如何处理的呢?假设 P0 有一个私有数据 x,三方之间可以简单交互一下实现:


方案 1: P2 生成一个随机数 r,发送给 P0/P1。然后 P0 本地设置 x0 = x - rP1 本地设置 x1 = r。此时 share(x) = (x0, x1) = (x - r, r),与上面的定义一致。


这是方案之一,后文基于这个方案进行讲解。在本文最后,我们会提一下实际落地时的进一步优化方案。


回到主线,结合 方案 1,我们以 Alice 的输入值 x = 1.2345 为例看下具体过程。


第一步,浮点数转定点数。


对于有数据输入的一方,需要先将真实的浮点数转成定点数。


浮点数转定点数:即浮点数乘以一个固定的缩放因子(scale,一般为)使其变成定点数(取其整数部分,舍弃小数部分)。当最后需要还原真实的原始浮点数时,用定点数除以缩放因子即可。


我们先选定一个缩放因子,这里取 scale =


经过缩放后,得到 x = 1.2345 * (1<<18) = 323616.768,取整数部分即 323616,用于后续计算。


这里是有精度损失的,但在精度允许的范围内,不会影响后面的计算。


第二步,生成随机数 r 也叫掩码(Masking value),用来隐藏真实值。


P2 生成一个随机数 r,是一个 64-bit 空间的无符号整数。(如,r =​ fdad72ecbfbefeb9。这里用十六进制表示,下同)


P2r 发送给 P0,P1。此时,P0,P1 都拥有一个相同的随机数 r 了。


第三步,设置秘密分享值。


按秘密分享 方案 1 的定义,P0 本地设置 x0 = x - rP1 本地设置 x1 = r。所以有:


P0x0 = 4f020 - fdad72ecbfbefeb9 = 2528d134045f167


P1x1 = fdad72ecbfbefeb9


4f020 是 323616 的十六进制表示。

如果计算结果大于 64 bit 的空间范围,需要对结果取模(64 位空间)。下同。


至此,我们获得了关于 x 的分享值,share(x) = (x0, x1) = (x - r, r) = (2528d134045f167, fdad72ecbfbefeb9)。


感兴趣的读者朋友可以验证一下 (x0 + x1) mod


同理,我们对 Bob 的输入值进行一样的处理。


上面三步,其实就是 private_console_input 的工作机制与过程。经过处理后,各方本地都存储着如下值:


P0P1P2
X02528d134045f167X1fdad72ecbfbefeb9X20
Y0d8e19bd0a532750Y1f271e642f5c29328Y20


我们用 Xi,Yi 表示 X,YPi 的分享值。(下同)

P2 为何是 0 呢?在本方案中 P2 作为一个辅助节点,不参与真正的逻辑计算。


我们可以看到,在处理隐私数据输入的整个过程中,P0 无法知道 y 值,P1 无法知道 x 值,P2 无法知道 xy 值。


最后,我们总结一下这三个主要阶段:


密文上的协同计算

这是计算的核心。


上一步,我们保证了输入的安全,没有信息的泄漏,各方无法单独拿到其他节点的私有输入。


接下来,看一下计算的代码,只有一行:


z = tf.multiply(x, y) # z = x * y
复制代码


在这个计算的过程中发生了什么?下面结合乘法(Multiply) 算子原理进行实例讲解。

Multiply 算子原理

乘法相对较为复杂,我们结合经典的 Beaver Triple 方法[2]加以介绍。该方法是由密码学家 Donald Beaver 在 1991 年提出,主要思想是通过乘法。协议基本原理如下:


输入: P0 拥有 X,Y 的秘密分享值 X0,Y0P1 拥有 X,Y 的秘密分享值 X1,Y1


这里有 share(X) = (X0, X1),share(Y) = (Y0, Y1)。在此案例中,这里的输入,就对接上一节所述的"隐私输入"的输出结果。


计算步骤:


  1. P2 本地生成一组随机数 A,B,C,且满足 C = A * B


A,B,C 的生成步骤:P2 随机生成 A0,A1,B0,B1,C0,令 A = A0 + A1, B = B0 + B1,得到 C = A * B, C1 = C - C0其中 Ai,Bi,CiA,B,C 的分享值。 这些都是在 P2 本地完成的。这也就是 P2 做为辅助节点的作用(用于随机数生成)。


这里 A,B,C 一般被称为三元组(Beaver’s Triple)。


比如,某次生成的随机数如下:


A02373edde1a0e5dcdA1ad483b77e4e5db41
B0d81a4646be1c0cb8B178222aff7dcc1ae8
C062a175e20f9a1542C1483498026c6ab57e


感兴趣的读者朋友可以验证一下。如 A = A0 + A1 = 2373edde1a0e5dcd + ad483b77e4e5db41 = d0bc2955fef4390e。这个 A 是个随机数


  1. P2 将上一步生成的随机数的秘密分享值分别发送给 P0,P1


即将 A0,B0,C0 发送给 P0;将 A1,B1,C1 发送给 P1


此时,P0,P1 拥有如下值:


P0P1
A02373edde1a0e5dcdA1ad483b77e4e5db41
B0d81a4646be1c0cb8B178222aff7dcc1ae8
C062a175e20f9a1542C1483498026c6ab57e


  1. P0 计算 E0F0P1 计算 E1F1。并交换 Ei,Fi


P0 本地计算 E0 = X0 - A0, F0 = Y0 - B0


P1 本地计算 E1 = X1 - A1, F1 = Y1 - B1


此时,P0,P1 拥有如下值:


P0P1
E0dede9f352637939aE150653774dad92378
F03573d3764c371a98F17a4fbb4377f67840


交换 Ei,Fi


P0E0,F0 发送给 P1P1E1,F1 发送给 P0。此时,P0,P1 都拥有 E0,F0,E1,F1


  1. P0,P1 本地计算 得到EF


P0,P1 各自本地计算 E = E0 + E1, F = F0 + F1


P0P1
E2f43d6aa0110b712E2f43d6aa0110b712
Fafc38eb9c42d92d8Fafc38eb9c42d92d8


  1. P0 本地计算 Z0P1 本地计算 Z1


现在,P0 已经拥有 A0,B0,C0,E,FP1 已经拥有 A1,B1,C1,E,F。有了这些就可以计算出 Z = X * Y 的秘密分享值 Z0,Z1 了。 即:


P0 本地计算 Z0 = E * B0 + A0 * F + C0


P1 本地计算 Z1 = E * B1 + A1 * F + C1 + E * F


P0P1
Z01db35d14c12aZ1ffffe24ca30611b0


正确性可以通过以下恒等式加以验证:


输出: P0,P1 分别持有 Z = X * Y 的秘密分享值 Z0,Z1


我们可以看到,从输入到计算再到输出,整个过程中,没有泄漏任何隐私数据。


整个算子计算结束时, P0 单独拥有 X0,Y0,A0,B0,C0,E0,F0,E1,F1,E,F,Z0P1 单独拥有 X1,Y1,A1,B1,C1,E0,F0,E1,F1,E,F,Z1P2 单独拥有 A0,B0,C0,A1,B1,C1,三方都无法单独得到 XYZ


最后,我们总结一下(1~5 对应着上面的步骤):


获取明文结果

输入到计算再到输出,各节点只能看到本地所单独拥有的秘密分享值(一些毫无规律的 64 位随机数),从上文也可以看到,节点是无法独自得到任何隐私数据的。那么,当计算结束后,如果想得到结果的明文,怎么获取呢?


Rosetta 提供了一个恢复明文的接口,使用很简单。


res = sess.run(rtt.SecureReveal(z, receive_party=4)) # 'b0100' means Charleyprint('z:', res)
复制代码


那这个 rtt.SecureReveal 是如何工作的呢?


其实非常简单:如果本方想要知道明文,只需要对方把他的秘密分享值发给我,然后本地相加即可。


比如,上一节结尾处,我们知道了各方 (P0/P1/P2) 的分享值如下:


P0P1P2
Z01db35d14c12aZ1ffffe24ca30611b0Z20


结合实例,Charley (P2) 想要获取结果明文,那么,P0,P1 将各自的分享值 Z0,Z1 发给 P2,然后 P2 本地相加即可。即: 1db35d14c12a + ffffe24ca30611b0 = 1ad2da (1757914)。我们将此值进一步再转换为浮点数,就可以得到我们想要的用户态的明文值了: 1757914 / (1 << 18)= 6.7059097

效率优化

上面介绍的 秘密分享multiply 算子 都是基于最基本的算法原理,在时间上和通信上的开销还是比较大的,在实际工程实现中,还可以进一步进行优化以提升性能。在介绍优化方案之前,先了解一下 什么是 PRF


PRF[3],Pseudo-Random Function。 简单来说,即给定一个随机种子 key,一个计数器 counter,执行 PRF(key, counter) ,会得到一个相同的随机数


补充说明一下。例如,P0,P1 执行 PRF(key01, counter01),会产生一个相同的随机数。这里的 key01counter01 对于 P0,P1 来说是一致的。程序会维护这两个值,对使用者来说是透明的。

关于秘密分享

来看看优化版本(假设: P0 有一个私有数据 x)。


  • 方案 2(优化版): P0,P1 使用 PRF(key01, counter) 本地同时生成一个相同的随机数 r。然后 P0 本地设置 x0 = x - rP1 本地设置 x1 = r。此时 share(x) = (x0, x1) = (x - r, r),与定义一致。此版本无需 P2 的参与。没有通信开销。


目前 Rosetta 开源版本中使用的正是此方案。


  • 方案 3(优化版): P0 设置 x0 = xP1 设置 x1 = 0 即可。此时 share(x) = (x, 0)此版本无需 P2 的参与。没有通信开销,也没有计算开销。


上述各个版本(包括方案 1),都是可行且安全的。可以看到P1/P2 并不知道 P0 的原始输入值。

关于 Multiply 算子

Multiply 算子中输入,输出部分没有变化,主要是计算步骤中的第 1 步与第 2 步有些许变化,以减少通信量。这里也只描述这两步,其余与前文相同。


在上文的描述中,我们知道 P2 生成三元组后,需要将其分享值发送给 P0,P1。当我们有了 PRF 后,可以这么做:


  1. P0,P2 使用 PRF(key02, counter02) 同时生成 A0,B0,C0P0,P1 使用 PRF(key12, counter12) 同时生成 A1,B1

  2. 然后,P2A = A0 + A1, B = B0 + B1,得到 C = A * B, C1 = C - C0P2C1 发送给 P1P2 的任务完成。

  3. 目前 Rosetta 开源版本中使用的是此方案。


相比于原始版本,优化版本只需要发送 C1,不用再发送 A0,A1,B0,B1,C0


在 Rosetta 中,我们还针对具体的各个不同的算子进行了一系列的算法、工程优化,欢迎感兴趣的读者来进一步了解。

小结

安全性是隐私 AI 框架的根本,在本篇文章中,我们结合隐私数据输入的处理和密文上乘法的实现,介绍了“随机数” 形式的密文是如何在多方之间流动,同时“神奇”的仍能保证计算逻辑的正确性的。我们这里对于安全性的说明是直观上的描述,而实际上,这些算法的安全性都是有严格数学证明的。感兴趣的读者可以进一步去探索相关的论文。


Rosetta 将持续集成安全可靠的密码学算法协议作为“隐私计算引擎”到框架后端中,也欢迎广大开发者参与到隐私 AI 的生态建设中来。

参考文献

[1] 秘密共享,https://en.wikipedia.org/wiki/Secret_sharing


[2] Beaver, Donald. “Efficient multiparty protocols using circuit randomization.” Annual International Cryptology Conference. Springer, Berlin, Heidelberg, 1991.


[3] PRF 的一个简单介绍,https://crypto.stanford.edu/pbc/notes/crypto/prf.html


作者介绍:


Rosetta 技术团队,一群专注于技术、玩转算法、追求高效的工程师。Rosetta 是一款基于主流深度学习框架 TensorFlow 的隐私 AI 框架,作为矩阵元公司大规模商业落地的重要引擎,它承载和结合了隐私计算、区块链和 AI 三种典型技术。目前 Rosetta 已经在 Github 开源(https://github.com/LatticeX-Foundation/Rosetta) ,欢迎关注并参与到 Rosetta 社区中来。


系列文章:


隐私 AI 工程技术实践指南:整体介绍


面向隐私AI的TensorFlow深度定制化实践


隐私AI框架中MPC协议的快速集成


2020-11-03 10:302404

评论

发布
暂无评论
发现更多内容

JavaScript slice 方法使用指南

Liam

JavaScript 程序员 前端 前端开发 slice

mac磁盘清理必备:Magic Disk Cleaner破解最新版

iMac小白

光纤网络排障分析

小魏写代码

以程序员的身份,教您使用API接口获取虾皮商品详情

Noah

【Windows 开发环境配置——NVIDIA 篇】CUDA、cuDNN、TensorRT 三件套安装

快乐非自愿限量之名

windows 开发环境

Richardson Software RazorSQL (多功能SQL数据库编辑器)注册版下载

iMac小白

选购美国云服务器,轻松打造高效网络

一只扑棱蛾子

美国服务器 美国云服务器

八个开源免费的低代码/无代码后端项目

高端章鱼哥

开源 低代码 无代码

数字马力面经和答案解析!社招岗

王磊

Java 面试 java面试

动作活体检测能力支持自定义扫描动作,开发者接入更高效

HarmonyOS SDK

HMS Core

新一代信息技术成为数字化转型满意度评价新要素

Geek_2d6073

技术贴 | SQL 执行 - 执行器优化

KaiwuDB

龙蜥社区联合浪潮信息发布《eBPF技术实践白皮书》(附下载链接)

OpenAnolis小助手

Linux 白皮书 ebpf 云栖大会 龙蜥社区

轻量级前端架构之:小程序技术

Speedoooo

小程序容器 小程序技术 小程序容器技术 微前端架构 轻量级前端架构

英伟达中国特供芯片是缩水版;华为 Mate60 Pro 国产零件价值占比 47%丨 RTE 开发者日报 Vol.84

声网

PDF Expert for Mac(PDF编辑阅读转换器)v3.6.0完整激活版

mac

PDF Expert 苹果mac Windows软件 PDF 工具

一文解码语言模型:语言模型的原理、实战与评估

EquatorCoco

概念介绍 语言模型

解决室内种植最大弊端的是方法—植物生长灯

电子信息发烧客

「mac」JProfiler 14 激活版(功能强大的Java性能分析工具)

iMac小白

JProfiler 14激活版 JProfiler 14下载 JProfiler 14 mac JProfiler 14破解版

简单地聊一聊Spring Boot的构架

快乐非自愿限量之名

前端 spring-boot

中馥集团双11当日发货销售额突破1000万!

电子信息发烧客

万字解析XML配置映射为BeanDefinition的源码

华为云开发者联盟

spring 开发 华为云 华为云开发者联盟

软件测试/测试开发丨探索Python中的函数定义和调用

测试人

软件测试

华为音乐枫叶音乐会,倾耳聆听心动音乐故事

最新动态

「mac」KeyShot Pro功能强大的3D渲染和动画制作软件

iMac小白

KeyShot Pro下载 KeyShot Pro破解版

石原子科技亮相2023成都市信息领域新产品发布会

StoneDB

MySQL 数据库 HTAP StoneDB

超级App的前端框架也可以足够轻量

FN0

前端框架 超级app

选购护眼台灯,全网都没有说清一个关键点!——照度均匀度

电子信息发烧客

NLP技术如何为搜索引擎赋能

不在线第一只蜗牛

nlp NLP 大模型 技术 优化体系

区块链开发:区块链软件开发包装相关解析

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

隐私AI框架中的数据流动与工程实现_AI&大模型_Rosetta技术团队_InfoQ精选文章