зеркало из https://github.com/mozilla/libprio.git
Hash batchID with shared secret to get PRG seed. (#104)
This commit is contained in:
Родитель
951cbd2b04
Коммит
80647f4887
|
@ -218,7 +218,7 @@ PrioPacketClient_set_data(const_PrioConfig cfg,
|
|||
return SECFailure;
|
||||
|
||||
P_CHECKC(PrioPRGSeed_randomize(&pB->shares.B.seed));
|
||||
P_CHECKA(prgB = PRG_new(pB->shares.B.seed));
|
||||
P_CHECKA(prgB = PRG_new(cfg, pB->shares.B.seed));
|
||||
|
||||
P_CHECKC(BeaverTriple_set_rand(cfg, pA->triple, pB->triple));
|
||||
P_CHECKA(client_data = MPArray_new_bool(data_len, data_in));
|
||||
|
|
44
prio/prg.c
44
prio/prg.c
|
@ -9,6 +9,7 @@
|
|||
#include <blapit.h>
|
||||
#include <mprio.h>
|
||||
#include <pk11pub.h>
|
||||
#include <sechash.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "prg.h"
|
||||
|
@ -29,8 +30,44 @@ PrioPRGSeed_randomize(PrioPRGSeed* key)
|
|||
return rand_bytes((unsigned char*)key, PRG_SEED_LENGTH);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
prg_seed_from_config_and_shared_secret(PrioPRGSeed key_out,
|
||||
const_PrioConfig cfg,
|
||||
const PrioPRGSeed shared_secret)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
HASHContext* ctx = NULL;
|
||||
const HASH_HashType hashType = HASH_GetHashTypeByOidTag(SEC_OID_SHA256);
|
||||
|
||||
P_CHECKA(ctx = HASH_Create(hashType));
|
||||
|
||||
HASH_Begin(ctx);
|
||||
|
||||
// Hash the shared_secret with the batch ID to
|
||||
// get the PRG seed. We might also want to
|
||||
// hash `num_data_fields` here, but since the
|
||||
// batch ID should be distinct per batch, this
|
||||
// should be enough.
|
||||
HASH_Update(ctx, shared_secret, PRG_SEED_LENGTH);
|
||||
HASH_Update(ctx, cfg->batch_id, cfg->batch_id_len);
|
||||
|
||||
unsigned int len;
|
||||
HASH_End(ctx, key_out, &len, PRG_SEED_LENGTH);
|
||||
|
||||
// Ensure that hash routine wrote out the
|
||||
// correct number of bytes.
|
||||
P_CHECKCB(len == PRG_SEED_LENGTH);
|
||||
|
||||
cleanup:
|
||||
if (ctx) {
|
||||
HASH_Destroy(ctx);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRG
|
||||
PRG_new(const PrioPRGSeed key_in)
|
||||
PRG_new(const_PrioConfig cfg, const PrioPRGSeed shared_secret)
|
||||
{
|
||||
PRG prg = malloc(sizeof(struct prg));
|
||||
if (!prg)
|
||||
|
@ -44,9 +81,10 @@ PRG_new(const PrioPRGSeed key_in)
|
|||
|
||||
P_CHECKA(prg->slot = PK11_GetInternalSlot());
|
||||
|
||||
// Create a mutable copy of the key.
|
||||
// Create the per-batch PRG key from the shared
|
||||
// secret and the PrioConfig.
|
||||
PrioPRGSeed key_mut;
|
||||
memcpy(key_mut, key_in, PRG_SEED_LENGTH);
|
||||
prg_seed_from_config_and_shared_secret(key_mut, cfg, shared_secret);
|
||||
|
||||
SECItem keyItem = { siBuffer, key_mut, PRG_SEED_LENGTH };
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ typedef const struct prg* const_PRG;
|
|||
* Initialize or destroy a pseudo-random generator.
|
||||
*/
|
||||
PRG
|
||||
PRG_new(const PrioPRGSeed key);
|
||||
PRG_new(const_PrioConfig cfg, const PrioPRGSeed shared_secret);
|
||||
void
|
||||
PRG_clear(PRG prg);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ PrioServer_new(const_PrioConfig cfg,
|
|||
s->prg = NULL;
|
||||
|
||||
P_CHECKA(s->data_shares = MPArray_new(s->cfg->num_data_fields));
|
||||
P_CHECKA(s->prg = PRG_new(seed));
|
||||
P_CHECKA(s->prg = PRG_new(s->cfg, seed));
|
||||
|
||||
cleanup:
|
||||
if (rv != SECSuccess) {
|
||||
|
@ -426,7 +426,7 @@ PrioVerifier_set_data(PrioVerifier v,
|
|||
}
|
||||
|
||||
if (v->s->idx == PRIO_SERVER_B) {
|
||||
P_CHECKA(prgB = PRG_new(v->clientp->shares.B.seed));
|
||||
P_CHECKA(prgB = PRG_new(v->s->cfg, v->clientp->shares.B.seed));
|
||||
P_CHECKC(PRG_get_array(prgB, v->data_sharesB, &v->s->cfg->modulus));
|
||||
P_CHECKC(PRG_get_array(prgB, v->h_pointsB, &v->s->cfg->modulus));
|
||||
}
|
||||
|
|
|
@ -19,13 +19,17 @@ mu_test__prg_simple(void)
|
|||
SECStatus rv = SECSuccess;
|
||||
PrioPRGSeed key;
|
||||
PRG prg = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg = PRG_new(key));
|
||||
PT_CHECKA(prg = PRG_new(cfg, key));
|
||||
|
||||
cleanup:
|
||||
mu_check(rv == SECSuccess);
|
||||
PRG_clear(prg);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -39,10 +43,13 @@ mu_test__prg_repeat(void)
|
|||
PrioPRGSeed key;
|
||||
PRG prg1 = NULL;
|
||||
PRG prg2 = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg1 = PRG_new(key));
|
||||
PT_CHECKA(prg2 = PRG_new(key));
|
||||
PT_CHECKA(prg1 = PRG_new(cfg, key));
|
||||
PT_CHECKA(prg2 = PRG_new(cfg, key));
|
||||
PT_CHECKA(buf1 = calloc(buflen, sizeof(unsigned char)));
|
||||
PT_CHECKA(buf2 = calloc(buflen, sizeof(unsigned char)));
|
||||
|
||||
|
@ -68,6 +75,7 @@ cleanup:
|
|||
free(buf2);
|
||||
PRG_clear(prg1);
|
||||
PRG_clear(prg2);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -85,10 +93,13 @@ mu_test__prg_repeat_int(void)
|
|||
PrioPRGSeed key;
|
||||
PRG prg1 = NULL;
|
||||
PRG prg2 = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg1 = PRG_new(key));
|
||||
PT_CHECKA(prg2 = PRG_new(key));
|
||||
PT_CHECKA(prg1 = PRG_new(cfg, key));
|
||||
PT_CHECKA(prg2 = PRG_new(cfg, key));
|
||||
|
||||
MPT_CHECKC(mp_init(&max));
|
||||
MPT_CHECKC(mp_init(&out1));
|
||||
|
@ -108,6 +119,7 @@ cleanup:
|
|||
mp_clear(&max);
|
||||
mp_clear(&out1);
|
||||
mp_clear(&out2);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -121,9 +133,12 @@ test_prg_once(int limit)
|
|||
|
||||
MP_DIGITS(&max) = NULL;
|
||||
MP_DIGITS(&out) = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg = PRG_new(key));
|
||||
PT_CHECKA(prg = PRG_new(cfg, key));
|
||||
|
||||
MPT_CHECKC(mp_init(&max));
|
||||
MPT_CHECKC(mp_init(&out));
|
||||
|
@ -139,6 +154,7 @@ cleanup:
|
|||
mp_clear(&max);
|
||||
mp_clear(&out);
|
||||
PRG_clear(prg);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -189,9 +205,12 @@ test_prg_distribution(int limit)
|
|||
|
||||
MP_DIGITS(&max) = NULL;
|
||||
MP_DIGITS(&out) = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg = PRG_new(key));
|
||||
PT_CHECKA(prg = PRG_new(cfg, key));
|
||||
PT_CHECKA(bins = calloc(limit, sizeof(int)));
|
||||
|
||||
MPT_CHECKC(mp_init(&max));
|
||||
|
@ -228,6 +247,7 @@ cleanup:
|
|||
mp_clear(&max);
|
||||
mp_clear(&out);
|
||||
PRG_clear(prg);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -259,9 +279,12 @@ test_prg_distribution_large(mp_int* max)
|
|||
PRG prg = NULL;
|
||||
|
||||
MP_DIGITS(&out) = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg = PRG_new(key));
|
||||
PT_CHECKA(prg = PRG_new(cfg, key));
|
||||
PT_CHECKA(bins = calloc(limit, sizeof(int)));
|
||||
|
||||
MPT_CHECKC(mp_init(&out));
|
||||
|
@ -290,6 +313,7 @@ cleanup:
|
|||
free(bins);
|
||||
mp_clear(&out);
|
||||
PRG_clear(prg);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -323,7 +347,7 @@ mu_test__prg_share_arr(void)
|
|||
PT_CHECKC(PrioPRGSeed_randomize(&seed));
|
||||
PT_CHECKA(arr = MPArray_new(10));
|
||||
PT_CHECKA(arr_share = MPArray_new(10));
|
||||
PT_CHECKA(prg = PRG_new(seed));
|
||||
PT_CHECKA(prg = PRG_new(cfg, seed));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
mp_set(&arr->data[i], i);
|
||||
|
@ -333,7 +357,7 @@ mu_test__prg_share_arr(void)
|
|||
|
||||
// Reset PRG
|
||||
PRG_clear(prg);
|
||||
PT_CHECKA(prg = PRG_new(seed));
|
||||
PT_CHECKA(prg = PRG_new(cfg, seed));
|
||||
|
||||
// Read pseudorandom values into arr
|
||||
PT_CHECKC(PRG_get_array(prg, arr, &cfg->modulus));
|
||||
|
@ -366,9 +390,12 @@ test_prg_range_once(int bot, int limit)
|
|||
MP_DIGITS(&lower) = NULL;
|
||||
MP_DIGITS(&max) = NULL;
|
||||
MP_DIGITS(&out) = NULL;
|
||||
PrioConfig cfg = NULL;
|
||||
|
||||
PT_CHECKA(cfg = PrioConfig_newTest(1));
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg = PRG_new(key));
|
||||
PT_CHECKA(prg = PRG_new(cfg, key));
|
||||
|
||||
MPT_CHECKC(mp_init(&max));
|
||||
MPT_CHECKC(mp_init(&out));
|
||||
|
@ -390,6 +417,7 @@ cleanup:
|
|||
mp_clear(&max);
|
||||
mp_clear(&out);
|
||||
PRG_clear(prg);
|
||||
PrioConfig_clear(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -413,3 +441,46 @@ mu_test_prg_range__odd(void)
|
|||
test_prg_range_once(7, 123);
|
||||
test_prg_range_once(99000, 993123);
|
||||
}
|
||||
|
||||
void
|
||||
mu_test_prg_uses_batch_id(void)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
PrioPRGSeed key;
|
||||
mp_int out1;
|
||||
mp_int out2;
|
||||
PRG prg1 = NULL;
|
||||
PRG prg2 = NULL;
|
||||
|
||||
MP_DIGITS(&out1) = NULL;
|
||||
MP_DIGITS(&out2) = NULL;
|
||||
PrioConfig cfg1 = NULL;
|
||||
PrioConfig cfg2 = NULL;
|
||||
|
||||
PT_CHECKA(cfg1 = PrioConfig_newTest(1));
|
||||
PT_CHECKA(cfg2 = PrioConfig_newTest(1));
|
||||
|
||||
// Two batch IDs are different. Check that
|
||||
// PRG outputs are actually different.
|
||||
cfg2->batch_id[0] = '\0';
|
||||
|
||||
PT_CHECKC(PrioPRGSeed_randomize(&key));
|
||||
PT_CHECKA(prg1 = PRG_new(cfg1, key));
|
||||
PT_CHECKA(prg2 = PRG_new(cfg2, key));
|
||||
|
||||
MPT_CHECKC(mp_init(&out1));
|
||||
MPT_CHECKC(mp_init(&out2));
|
||||
|
||||
PT_CHECKC(PRG_get_int(prg1, &out1, &cfg1->modulus));
|
||||
PT_CHECKC(PRG_get_int(prg2, &out2, &cfg1->modulus));
|
||||
mu_check(mp_cmp(&out1, &out2) != 0);
|
||||
|
||||
cleanup:
|
||||
mu_check(rv == SECSuccess);
|
||||
mp_clear(&out1);
|
||||
mp_clear(&out2);
|
||||
PRG_clear(prg1);
|
||||
PRG_clear(prg2);
|
||||
PrioConfig_clear(cfg1);
|
||||
PrioConfig_clear(cfg2);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче