Created
April 8, 2020 19:30
-
-
Save dirkx/008565e96711ab522f8968cf597199fc to your computer and use it in GitHub Desktop.
attempt at C version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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