本文介绍了PRIO3方法,它是一种用于在保护用户隐私的前提下高效收集聚合数据的多方分布式聚合协议(DAP)。PRIO3允许在不泄露个人信息的情况下计算统计数据,例如手机制造商想要了解其用户性别的分布情况。文章通过代码示例展示了如何使用PRIO3进行计数和计算聚合统计,并提到了其在求和与直方图方面的应用。
收集聚合数据是计算领域最赚钱的行业之一,但我们如何在不侵犯用户隐私的情况下高效地收集数据?嗯,多方分布式聚合协议(DAP)是一个答案,而 PRIO3 方法是目前最好的方法之一。
虽然安全措施已应用于静态数据和空中传输数据,但我们通常仍然对明文数据进行计算。这引发了很多问题,尤其是处理器可以确定 PII(个人身份信息)和诸如秘密加密密钥之类的信息。一种方法是使用 MPC(多方计算),我们可以将计算分解成更小的块,并让每个参与方分享计算。其中一个最好的应用是以隐私感知的方式收集统计信息。
例如,移动电话制造商可能想要确定其电话所有者的性别比例,但实际上并不透露任何特定的人。为此,每个客户端设备为其性别创建一个 SNIP(秘密共享的非交互式证明)。在 PRIO3 中,这是一个快速高效的零知识证明。然后,服务器可以接收这些 SNIP,并检查其有效性。检查完毕后,他们可以更新其本地累加器,以进行当前的统计信息聚合。然后,当我们想要从客户端设备中揭示性别比例时,他们可以发布其聚合总数:
总的来说,由于创建了其性别的零知识证明,因此没有一个服务器可以确定客户端是男性还是女性;但是,我们仍然可以计算总数。使用 PRIO3,没有一个服务器可以查看明文数据,并且基于经典论文 [ 这里][1]:
PRIO3 的实现可以被普遍地看作是用于隐私测量的多方分布式聚合协议(DAP)的一部分,并且目前正在 IETF 进行标准化 [ 这里]:
我们将使用 PRIO3 为布尔值(计数)创建多个共享,然后将数据聚合回去。核心分析是对某事物为 True 还是 False 的基本计数,数据集为 {true, false, true, true},并将计算 true 值的数量 [ 这里]:
package main
import (
"fmt"
"crypto/rand"
"os"
"io"
"strconv"
"github.com/cloudflare/circl/vdaf/prio3/count"
)
func fromReader[T any](r io.Reader) (z T) {
switch zz := any(&z).(type) {
case *count.Nonce:
_, _ = r.Read(zz[:])
case *count.VerifyKey:
_, _ = r.Read(zz[:])
}
return
}
var Context = []byte("Test")
func main() {
NumShares := uint8(2)
input := []bool{true,false,true, true}
argCount := len(os.Args[1:])
if argCount > 0 {
a,_ := strconv.Atoi(os.Args[1])
NumShares=uint8(a)
}
c, _ := count.New(NumShares, Context)
params := c.Params()
shares := params.Shares()
aggShares := make([]count.AggShare, shares)
for i := range aggShares {
aggShares[i] = c.AggregateInit()
}
for _, mi := range input {
nonce := fromReader[count.Nonce](rand.Reader)
verifyKey := fromReader[count.VerifyKey](rand.Reader)
randb := make([]byte, params.RandSize())
_, _ = io.ReadFull(rand.Reader, randb)
var pubShare count.PublicShare
var inputShares []count.InputShare
pubShare, inputShares, _ = c.Shard(mi, &nonce , randb)
var prepStates []*count.PrepState
var outboundPrepShares []count.PrepShare
for i := range shares {
state, share, _ := c.PrepInit(&verifyKey, &nonce, i, pubShare, inputShares[i])
prepStates = append(prepStates, state)
outboundPrepShares = append(outboundPrepShares, *share)
}
var prepMsg *count.PrepMessage
prepMsg, _ = c.PrepSharesToPrep(outboundPrepShares)
var outShare *count.OutShare
for i := range shares {
outShare,_ = c.PrepNext(prepStates[i], prepMsg)
c.AggregateUpdate(&aggShares[i], outShare)
}
}
numMeas := uint(len(input))
aggResult, _ := c.Unshard(aggShares, numMeas)
fmt.Printf("Inputs: %v\n\n", input)
fmt.Printf("Number of inputs: %d\n\n", numMeas)
fmt.Printf("Number of shares: %d\n\n", NumShares)
fmt.Printf("Aggregated Count %d\n\n", *aggResult)
for i := range shares {
fmt.Printf("Share %v\n", aggShares[i])
}
}
以及一个示例运行 [ 这里]:
Inputs: [true false true true]
Number of inputs: 4
Number of shares: 4
Aggregated Count 3
Share {[[7227276485192055052]]}
Share {[[673113590378828220]]}
Share {[[14679250781088487564]]}
Share {[[14313847295054699691]]}
求和的例子在这里:
用于使用 Go 进行求和的可验证分布式聚合函数的 PRIO3
以及一个直方图:
用于使用 Go 制作直方图的可验证分布式聚合函数的 PRIO3
[1] Corrigan-Gibbs, H., & Boneh, D. (2017). Prio: Private, robust, and scalable computation of aggregate statistics. In 14th USENIX symposium on networked systems design and implementation (NSDI 17) (pp. 259–282).
- 原文链接: billatnapier.medium.com/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!