La recopilación de datos agregados es una de las industrias más rentables en la informática, pero ¿cómo podemos recopilar datos de manera eficiente sin violar la privacidad del usuario? Bueno, un Protocolo de Agregación Distribuida Multi-partito (DAP) es una respuesta, y el método PRIO3 es uno de los mejores que existen para esto.
Si bien la seguridad se ha aplicado a los datos en reposo y en el aire, a menudo todavía realizamos nuestros cálculos en datos de texto sin formato. Esto abre muchos problemas, especialmente que el procesador puede determinar la PII (Información de Identificación Personal) y cosas como las claves de cifrado secretas. Un enfoque es utilizar MPC (Computación Multi-partito), y donde podemos dividir nuestro cálculo en bloques más pequeños, y dar a cada una de las partes una parte del cálculo. Una de las mejores aplicaciones de esto es recopilar estadísticas de una manera que respete la privacidad.
Por ejemplo, un fabricante de teléfonos móviles puede querer determinar el equilibrio de género de los propietarios de sus teléfonos, pero no revelar realmente a ninguna persona específica. Para esto, cada dispositivo cliente crea un SNIP (prueba no interactiva de secreto compartido) para su género. Dentro de PRIO3, esta es una prueba de conocimiento cero rápida y eficiente. Luego, los servidores pueden recibir estos SNIPs y verificar su validez. Una vez verificados, pueden actualizar sus acumuladores locales para la agregación actual de estadísticas. Luego, cuando queremos revelar el equilibrio de género de los dispositivos cliente, pueden publicar sus totales de agregación:
En general, ninguno de los servidores puede determinar si el cliente es hombre o mujer, ya que se crea una prueba de conocimiento cero de su género; sin embargo, todavía podemos calcular el total. Con PRIO3, ninguno de los servidores llega a ver datos de texto sin formato, y se basa en un artículo clásico [here][1]:
La implementación de PRIO3 puede verse generalmente como parte de un Protocolo de Agregación Distribuida Multi-partito (DAP) para la medición de la privacidad, y que ahora está progresando para la estandarización con el IETF [here]:
Usaremos PRIO3 para crear una serie de acciones para valores booleanos (recuento), y luego agregaremos los datos de vuelta. El análisis central es un recuento básico de si algo es True o False, y el conjunto de datos es {true, false, true, true} y contará el número de valores 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])
}
}
Y una muestra de ejecución [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]]}
Un ejemplo de suma está aquí:
PRIO3 for Verifiable Distributed Aggregation Functions for Summation with GoY para un histograma:
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).