彙總資料的收集是運算中最有利可圖的產業之一,但我們如何在不侵犯使用者隱私的情況下有效地收集資料?嗯,多方分散式彙總協定 (DAP) 是一個答案,而 PRIO3 方法是目前最好的方法之一。
雖然安全性已應用於靜止和傳輸中的資料,但我們通常仍然對明文資料進行運算。這引發了許多問題,尤其是處理器可以確定 PII(個人身份資訊)和諸如秘密加密金鑰之類的東西。一種方法是使用 MPC(多方運算),我們可以將運算分成更小的區塊,並讓每個參與方分享運算。其中一個最好的應用是以保護隱私的方式收集統計資料。
例如,行動電話製造商可能想要確定其手機擁有者的性別比例,但實際上不透露任何特定的人。為此,每個客戶端設備都會為其性別建立一個 SNIP(秘密共享的非互動式證明)。在 PRIO3 中,這是一個快速且高效的零知識證明。然後,伺服器可以接收這些 SNIP,並檢查它們的有效性。檢查完成後,它們可以更新其本地累加器,以進行當前統計資料的彙總。然後,當我們想要揭示來自客戶端設備的性別比例時,它們可以發布其彙總總數:
總體而言,由於創建了性別的零知識證明,因此沒有任何伺服器可以確定客戶端是男性還是女性;但是,我們仍然可以計算總數。使用 PRIO3,沒有任何伺服器可以查看明文資料,並且基於經典論文 [here][1]:
PRIO3 實作通常可以被視為隱私測量的多方分散式彙總協定 (DAP) 的一部分,並且目前正在 IETF 中進行標準化 [here]:
我們將使用 PRIO3 為布林值(計數)創建多個共享,然後將資料彙總回來。核心分析是對某事物是 True 還是 False 進行基本計數,資料集是 {true, false, true, true},並將計算 true 值的數量 [here]:
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])
}
}
以及一個範例執行 [here]:
Inputs: [true false true true]
Number of inputs: 4
Number of shares: 4
Aggregated Count 3
Share {[[7227276485192055052]]}
Share {[[673113590378828220]]}
Share {[[14679250781088487564]]}
Share {[[14313847295054699691]]}
以下是一個求和的範例:
PRIO3 for Verifiable Distributed Aggregation Functions for Summation with Go以及一個直方圖:
PRIO3 for Verifiable Distributed Aggregation Functions for Histograms with Go[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).