Skip to content

Instantly share code, notes, and snippets.

@dirkx
Created April 8, 2020 19:30
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/008565e96711ab522f8968cf597199fc to your computer and use it in GitHub Desktop.
Save dirkx/008565e96711ab522f8968cf597199fc to your computer and use it in GitHub Desktop.
attempt at C version
#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 <assert.h>
#include <strings.h>
#include <stdlib.h>
#define SKT_LEN (32)
#define SKT_BITLEN (SKT_LEN * 8)
#define SKT_EHPID_LEN (16)
#define SKT_BROADCAST_KEY ((uint8_t*)"Decentralized Privacy-Preserving Proximity Tracing")
typedef struct dp3t_skt_t {
uint8_t key[SKT_LEN];
} dp3t_skt_t;
typedef struct dp3t_eph_t {
uint8_t id[SKT_EHPID_LEN];
} dp3t_eph_t;
typedef enum {
DPT3T_OK,
DPT3T_ERR,
} dp3t_err_t;
dp3t_err_t generate_skt( dp3t_skt_t * skt) {
assert(sizeof(skt->key) == SHA256_DIGEST_LENGTH);
assert(SKT_BITLEN/8 == SHA256_DIGEST_LENGTH);
return (1 == RAND_bytes(skt->key, sizeof(skt->key))) ? DPT3T_OK : DPT3T_ERR;
}
dp3t_err_t set_skt( dp3t_skt_t * skt, char *hex_string) {
if (strlen(hex_string) != SHA256_DIGEST_LENGTH*2)
return DPT3T_ERR;
for(int i = 0;i<SHA256_DIGEST_LENGTH;i++) {
char bt[3] = { hex_string[(i<<1)+0], hex_string[(i<<1)+1], 0};
skt->key[i] = strtoul(bt, NULL,16);
}
return DPT3T_OK;
}
dp3t_err_t next_skt( dp3t_skt_t * nextkey, dp3t_skt_t * skt) {
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, skt->key,SKT_LEN);
SHA256_Final(nextkey->key, &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_skt( dp3t_skt_t * skt) {
printf("SKT: ");
for(size_t i = 0; i < sizeof(skt->key); i++)
printf("%02X",skt->key[i]);
printf("\n");
}
void print_ephid( dp3t_eph_t * e) {
printf("EPH: ");
for(size_t i = 0; i < sizeof(e->id); i++)
printf("%02X",e->id[i]);
printf("\n");
}
/* Zenroom version:
for i = ACK.moments,1,-1 do
local PRF = SHA256:hmac(ACK.secret_day_key, BROADCAST_KEY)
local PRG = AES.ctr(PRF, OCTET.from_number(0), OCTET.from_number(i))
table.insert(ACK.ephemeral_ids, PRG)
end
pub fn get_ephemeral(&self, num_tokens: u32) -> Vec<Ephemeral> {
let key = hmac::Key::new(hmac::HMAC_SHA256, &self.key);
let aes_key = hmac::sign(&key, b"Decentralized Privacy-Preserving Proximity Tracing");
let cipher = Aes256::new(aes_key.as_ref().into());
let mut result = Vec::with_capacity(num_tokens as usize);
let day = self.julian_day;
for i in 0..num_tokens {
let mut serial = [0u8; 16];
serial[12..16].copy_from_slice(&i.to_be_bytes());
let mut block = GenericArray::clone_from_slice(&serial);
cipher.encrypt_block(&mut block);
let mut token = [0; 16];
token.copy_from_slice(&block);
result.push(Ephemeral { day, token })
}
result
}
*/
dp3t_err_t generate_ephids(dp3t_skt_t * skt, dp3t_eph_t list[], size_t num) {
uint8_t aes_key[SHA256_DIGEST_LENGTH];
unsigned int len =SHA256_DIGEST_LENGTH;
// local PRF = SHA256:hmac(ACK.secret_day_key, BROADCAST_KEY)
// 446563656e7472616c697a656420507269766163792d50726573657276696e672050726f78696d6974792054726163696e67
// unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, const unsigned char *d, size_t n, unsigned char *md, unsigned int *md_len);
//
HMAC(EVP_sha256(),
skt->key, SKT_LEN,// HMAC- key (all 0's in this test)
SKT_BROADCAST_KEY, sizeof(SKT_BROADCAST_KEY), // key to be digested and signed
aes_key, &len);
// 83b544f1dfb6564e27f6978f43de6c5dfafc510709f270c91daa553fc11cefe1
//
print_hex(aes_key, SHA256_DIGEST_LENGTH);
const EVP_CIPHER * evp_cypher =EVP_get_cipherbyname("aes-256-cbc");
assert(evp_cypher != NULL);
for(int i = 0; i < num; i++) {
uint8_t iv[SKT_EHPID_LEN];
bzero(iv,SKT_EHPID_LEN);
*(uint32_t*)(iv+8) = htonl(i); // big endian or network order.
printf("IV: "); print_hex(iv,16);
/* IV: 00000000000000000000000000000000 - 16 bytes.
* IV: 00000000000000000000000100000000
* IV: 00000000000000000000000200000000
* IV: 00000000000000000000000300000000
* IV: 00000000000000000000000400000000
* IV: 00000000000000000000000500000000
*/
uint8_t zeros[SKT_EHPID_LEN];
bzero(zeros,SKT_EHPID_LEN);
EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new();
EVP_CipherInit(ctx, evp_cypher, aes_key /* key */, iv,1);
int outlen = SKT_EHPID_LEN;
EVP_CipherUpdate(ctx, list[i].id, &outlen, zeros /* plaintext */, SKT_EHPID_LEN);
assert(outlen == SKT_EHPID_LEN);
};
return 0;
}
int main(int argc, const char * argv[]) {
RAND_poll();
dp3t_skt_t skt_null;
assert(DPT3T_OK == set_skt(&skt_null, "0000000000000000000000000000000000000000000000000000000000000000"));
// 446563656e7472616c697a656420507269766163792d50726573657276696e672050726f78696d6974792054726163696e67
printf("BKEY: "); print_hex(SKT_BROADCAST_KEY, sizeof(SKT_BROADCAST_KEY));
// 0000000000000000000000000000000000000000000000000000000000000000
print_skt(&skt_null);
dp3t_skt_t skt_1;
assert(DPT3T_OK == next_skt(&skt_1, &skt_null));
// 66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
print_skt(&skt_1);
const int N = 10;
dp3t_eph_t list[N];
generate_ephids(&skt_null, list, N);
for(int i = 0; i < N; i++ ) {
printf("%008d ", i);
print_ephid(&list[i]); // a747e729bf2e3de3ec6ecbdb0f889f5b
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment