Skip to content

Instantly share code, notes, and snippets.

@dirkx
Created April 9, 2020 15:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dirkx/d42c7553bbf3f601725d972fb76e0dd3 to your computer and use it in GitHub Desktop.
Save dirkx/d42c7553bbf3f601725d972fb76e0dd3 to your computer and use it in GitHub Desktop.
/* Copyright © 2020 Dirk-Willem van Gulik. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef dp3t_v2_h
#define dp3t_v2_h
#include <stdio.h>
#include <stdint.h>
#define EPHID_SEED_LEN (32 /* bytes */)
#define EPHID_IDLEN (16 /* bytes */)
#define EPHID_HASHLEN (256/8)
typedef struct dp3t_eph_seed_t {
uint8_t id[EPHID_SEED_LEN];
} dp3t_eph_seed_t;
typedef struct dp3t_eph_t {
uint8_t id[EPHID_IDLEN];
} dp3t_eph_t;
typedef enum {
DPT3T_OK,
DPT3T_ERR,
} dp3t_err_t;
dp3t_err_t generate_eph_seed( dp3t_eph_seed_t * seed);
dp3t_err_t generate_eph_ephid( dp3t_eph_seed_t * seed, dp3t_eph_t * key);
dp3t_err_t populate_cfentry(uint8_t * buff, dp3t_eph_t * ephid, uint32_t t);
void print_hex(uint8_t * buff, size_t len);
void print_seed( dp3t_eph_seed_t * x);
void print_ephid( dp3t_eph_t * x);
#endif /* dp3t_core_h */
/* Copyright © 2020 Dirk-Willem van Gulik. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "libdp3t_v2.h"
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/hmac.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <assert.h>
#include <strings.h>
#include <stdlib.h>
dp3t_err_t generate_eph_seed( dp3t_eph_seed_t * seed) {
return (1 == RAND_bytes(seed->id, sizeof(seed->id))) ? DPT3T_OK : DPT3T_ERR;
}
dp3t_err_t generate_eph_ephid(dp3t_eph_seed_t * seed, dp3t_eph_t * key) {
uint8_t buff[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, seed->id,EPHID_SEED_LEN);
SHA256_Final(buff, &sha256);
// https://github.com/DP-3T/documents/issues/93
memcpy(key->id, buff, EPHID_IDLEN);
return DPT3T_OK;
}
dp3t_err_t populate_cfentry(uint8_t * buff, dp3t_eph_t * ephid, uint32_t t) {
assert(buff);
uint8_t hashed_identity[EPHID_IDLEN + sizeof(t)];
memcpy(hashed_identity,ephid->id,EPHID_IDLEN);
uint32_t t_wire = htonl(t);
memcpy(hashed_identity+EPHID_IDLEN,&t_wire,sizeof(t_wire));
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, hashed_identity,sizeof(hashed_identity));
assert(SHA256_DIGEST_LENGTH == EPHID_HASHLEN);
SHA256_Final(buff, &sha256);
return DPT3T_OK;
};
void print_hex(uint8_t * buff, size_t len) {
for(int i = 0; i < len; i++)
printf("%02x", buff[i]);
printf("\n");
};
void print_seed( dp3t_eph_seed_t * x) {
printf("SKT: "); print_hex(x->id, EPHID_SEED_LEN);
}
void print_ephid( dp3t_eph_t * x) {
printf("EPH: "); print_hex(x->id, EPHID_IDLEN);
}
#include "libdp3t_v2.h"
#include "cuckoo_filter.h"
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/hmac.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <assert.h>
#include <strings.h>
#include <stdlib.h>
#include "cuckoo_filter.h"
#define TRIVIAL_CUCKOO_IMPLEMENTATION_32BIT_HASH (1)
dp3t_err_t generate_fake_ephid( dp3t_eph_t * ephid) {
return (1 == RAND_bytes(ephid->id, sizeof(ephid->id))) ? DPT3T_OK : DPT3T_ERR;
}
void testvectors() {
dp3t_eph_seed_t seed;
assert(DPT3T_OK == generate_eph_seed (&seed));
print_seed(&seed);
dp3t_eph_t ephid;
assert(DPT3T_OK == generate_eph_ephid (&seed, &ephid));
print_ephid(&ephid);
uint32_t t = 0;
#define N_MET (500000)
struct localrec {
uint8_t * hash;
void *auxdata;
} records[N_MET];
printf("\nLocal gathering\n");
for(int i = 0; i < N_MET; i++) {
dp3t_eph_t ephid_received; // as received
if (i == N_MET/2) {
ephid_received = ephid;
} else {
assert(DPT3T_OK == generate_fake_ephid(&ephid_received));
};
records[i].hash = malloc(EPHID_HASHLEN);
assert(DPT3T_OK == populate_cfentry(records[i].hash,&ephid_received, t));
if (i<10) { printf("%s %03d: ",i == N_MET/2 ? "---->" :"local", i); print_hex(records[i].hash, EPHID_HASHLEN);};
};
// Periodically (e.g., every 4 hours), the backend creates a new Cuckoo filter F and for each pair (t, seed ) uploaded by an infected patients it inserts
// TRUNCATE128(H(H(seedt)||t))
#define MAX_KEY_COUNT (500000)
#define MAX_KICK_ATTEMTPS (100)
#if TRIVIAL_CUCKOO_IMPLEMENTATION_32BIT_HASH
cuckoo_filter_init(1024 * 1024);
#else
cuckoo_filter_t *filter_central;
uint32_t cuckoo_seed;
assert(1 == RAND_bytes((uint8_t*)&cuckoo_seed, sizeof(cuckoo_seed)));
assert(CUCKOO_FILTER_OK == cuckoo_filter_new(&filter_central, MAX_KEY_COUNT, MAX_KICK_ATTEMTPS,cuckoo_seed));
#endif
#define INFECTED (1)
printf("\nBackend gathering\n");
{
// first we add our real seed - i.e. we say we are infected
uint8_t buff[EPHID_HASHLEN];
assert(DPT3T_OK == populate_cfentry(buff,&ephid, t));
#if TRIVIAL_CUCKOO_IMPLEMENTATION_32BIT_HASH
cuckoo_filter_put(buff, buff);
#else
assert(CUCKOO_FILTER_OK == cuckoo_filter_add(filter_central, buff, EPHID_HASHLEN));
#endif
printf("REMO %03d: ",999); print_hex(buff, EPHID_HASHLEN);
// now add a lot of 'cruft' to the central filter - as if others reported too.
for(int i = 0; i < 10; i++) {
uint8_t fake[EPHID_HASHLEN];
assert(1 == RAND_bytes(fake, sizeof(fake)));
if (i < 10) {printf("remo %03d: ",i); print_hex(fake, sizeof(fake));};
#if TRIVIAL_CUCKOO_IMPLEMENTATION_32BIT_HASH
cuckoo_filter_put(fake, fake);
#else
assert(CUCKOO_FILTER_OK == cuckoo_filter_add(filter_central, fake, EPHID_HASHLEN));
#endif
}
};
printf("\nChecking for needed\n");
// Now check if we can find the needle in this haystack
int contaminated = 0;
for(int i = 0; i < N_MET; i++) {
#if TRIVIAL_CUCKOO_IMPLEMENTATION_32BIT_HASH
uint8_t * val = cuckoo_filter_get(records[i].hash);
if (val) contaminated++;
if (i < 10) printf("%s %03d: ",val ? "found" : "nope ", i);
#else
CUCKOO_FILTER_RETURN r = cuckoo_filter_contains(filter_central,records[i].hash,EPHID_HASHLEN);
if (i < 10) printf("%s %03d: ",r ==CUCKOO_FILTER_NOT_FOUND ? "NTFND" :( (r ==CUCKOO_FILTER_FULL ) ? "FILLD" : "ERROR"), i);
#endif
if (i < 10) print_hex(records[i].hash, EPHID_HASHLEN);
};
printf("Got %d contaminated\n",contaminated);
assert(contaminated == INFECTED);
#if TRIVIAL_CUCKOO_IMPLEMENTATION_32BIT_HASH
#else
cuckoo_filter_free(&filter_central);
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment