|隐私数据在隐私AI框架中的安全流动( 二 )

  • Charley拿到的结果会不会被 Alice、 Bob知道?
  • 整个程序运行过程中 , 有没有其他数据的泄漏?
  • 如果前几问的回答都是否定的 , 那 Charley 又是如何得到明文?
  • 在回答这些问题之前 , 为简化描述、突出本质 , 我们需要简单介绍一下MPC实际落地中常用的安全假设 。
    假定系统中有 3 个节点 ,P0/P1/P2 , 其中成P0/P1为数据参与方 , 而P2是辅助节点 , 用于随机数生成 。
    • 只考虑半诚实( Semi-Honest )安全模型 , 即三方都会遵守协议执行的流程 , 并且其中诚实者占多数( Honest-Majority) , 也就是说三个节点中只会有一个“坏人” 。 更为复杂的恶意( Malicious)模型等安全场景可参考其他相关论文 。
    • 内部数据类型为64位无符号整型 , 即uint64_t 。
    下面我们就按照输入--计算--输出的顺序 , 详细介绍 Rosetta 中数据的表示与流动 , 以及所用到相关技术与算法在工程上的优化实现 。
    |隐私数据在隐私AI框架中的安全流动
    本文插图

    隐私数据的输入
    隐私计算问题 , 首先要解决的是隐私数据的输入 。
    在上述案例中 , 是通过如下两行代码来完成私有数据的安全输入的:
    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_input,等 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:生成一个随机数 r , 发送给 P0/P1 。 然后本地设置 x0 = x - r ,P1 本地设置 x1 = r 。 此时 share(x) = (x0, x1) = (x - r, r) , 与上面的定义一致 。
    这是方案之一 , 后文基于这个方案进行讲解 。 在本文最后 , 我们会提一下实际落地时的进一步优化方案 。
    回到主线 , 结合方案1 , 我们以Alice 的输入值x = 1.2345为例看下具体过程 。
    第一步 , 浮点数转定点数 。
    对于有数据输入的一方 , 需要先将真实的浮点数转成定点数 。
    浮点数转定点数:即浮点数乘以一个固定的缩放因子(scale , 一般为2^k)使其变成定点数(取其整数部分 , 舍弃小数部分) 。 当最后需要还原真实的原始浮点数时 , 用定点数除以缩放因子即可 。
    我们先选定一个缩放因子 , 这里取scale= 2^(18) 。
    经过缩放后 , 得到 x = 1.2345 * (1<<18) = 323616.768 , 取整数部分即323616 , 用于后续计算 。
    这里是有精度损失的 , 但在精度允许的范围内 , 不会影响后面的计算 。
    第二步 , 生成随机数 r 。 也叫掩码(Maskingvalue) , 用来隐藏真实值 。
    p2生成一个随机数 r , 是一个 64-bit 空间的无符号整数 。 (如 , r = fdad72ecbfbefeb9 。 这里用十六进制表示 , 下同)


    推荐阅读