implementation of the cryptographic primitives
This commit is contained in:
		
							
								
								
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | .vs/ | ||||||
|  | *.o | ||||||
|  | *.swp | ||||||
|  | ~* | ||||||
|  | *~ | ||||||
|  | .idea/ | ||||||
|  | cmake-build-debug/ | ||||||
|  | cmake-build-debugandtest/ | ||||||
|  | cmake-build-release/ | ||||||
|  | *.stackdump | ||||||
|  | *.coredump | ||||||
|  | compile_commands.json | ||||||
|  | /build* | ||||||
|  | /result* | ||||||
|  | .clangd | ||||||
|  | .cache | ||||||
|  |  | ||||||
|  | .DS_Store | ||||||
|  | .AppleDouble | ||||||
|  | .LSOverride | ||||||
|  |  | ||||||
|  | CMakeLists.txt.user* | ||||||
|  | CMakeCache.txt | ||||||
|  |  | ||||||
|  | *.tox | ||||||
|  | imgui.ini | ||||||
							
								
								
									
										39
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | cmake_minimum_required(VERSION 3.9 FATAL_ERROR) | ||||||
|  |  | ||||||
|  | project(p2prng) | ||||||
|  |  | ||||||
|  | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ||||||
|  |  | ||||||
|  | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") | ||||||
|  | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") | ||||||
|  | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") | ||||||
|  |  | ||||||
|  | add_library(p2prng | ||||||
|  | 	./src/p2prng.h | ||||||
|  | 	./src/p2prng.c | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | find_package(unofficial-sodium CONFIG QUIET) | ||||||
|  | find_package(sodium QUIET) | ||||||
|  | find_package(PkgConfig QUIET) | ||||||
|  | if(unofficial-sodium_FOUND) # vcpkg | ||||||
|  | 	if(TARGET unofficial-sodium::sodium) | ||||||
|  | 		target_link_libraries(p2prng unofficial-sodium::sodium) | ||||||
|  | 	endif() | ||||||
|  | 	if(TARGET unofficial-sodium::sodium_config_public) | ||||||
|  | 		target_link_libraries(p2prng unofficial-sodium::sodium_config_public) | ||||||
|  | 	endif() | ||||||
|  | elseif(sodium_FOUND) | ||||||
|  | 	target_link_libraries(p2prng sodium) | ||||||
|  | else() | ||||||
|  | 	if(PkgConfig_FOUND) | ||||||
|  | 		pkg_check_modules(pkgconf_sodium IMPORTED_TARGET libsodium) | ||||||
|  | 	endif() | ||||||
|  |  | ||||||
|  | 	if (TARGET PkgConfig::pkgconf_sodium) | ||||||
|  | 		target_link_libraries(p2prng PkgConfig::pkgconf_sodium) | ||||||
|  | 	else() | ||||||
|  | 		message(SEND_ERROR "missing libsodium") | ||||||
|  | 	endif() | ||||||
|  | endif() | ||||||
|  |  | ||||||
							
								
								
									
										71
									
								
								src/p2prng.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/p2prng.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | |||||||
|  | #include "./p2prng.h" | ||||||
|  |  | ||||||
|  | #include <sodium.h> | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  |  | ||||||
|  | static_assert(P2PRNG_MAC_KEY_LEN == crypto_auth_KEYBYTES, "key sizes differ"); | ||||||
|  | static_assert(P2PRNG_MAC_LEN == crypto_auth_BYTES, "mac sizes differ"); | ||||||
|  |  | ||||||
|  | static_assert(P2PRNG_MAC_KEY_LEN == P2PRNG_LEN, "key not 256"); | ||||||
|  | static_assert(P2PRNG_MAC_LEN == P2PRNG_LEN, "mac not 256"); | ||||||
|  |  | ||||||
|  | static_assert(P2PRNG_COMBINE_LEN == P2PRNG_LEN, "combine not 256"); | ||||||
|  |  | ||||||
|  | int p2prng_auth_create(uint8_t out_key[P2PRNG_MAC_KEY_LEN], uint8_t out_mac[P2PRNG_MAC_LEN], const uint8_t* msg, uint32_t msg_len) { | ||||||
|  | 	// could replace with randombytes_buf() to avoid key size check | ||||||
|  | 	crypto_auth_keygen(out_key); | ||||||
|  |  | ||||||
|  | 	return crypto_auth(out_mac, msg, msg_len, out_key); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int p2prng_auth_verify(const uint8_t key[P2PRNG_MAC_KEY_LEN], const uint8_t mac[P2PRNG_MAC_LEN], const uint8_t* msg, uint32_t msg_len) { | ||||||
|  | 	return crypto_auth_verify(mac, msg, msg_len, key); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int p2prng_combine_init(uint8_t out_hash[P2PRNG_COMBINE_LEN], const uint8_t* msg, uint32_t msg_len) { | ||||||
|  | 	return crypto_generichash(out_hash, P2PRNG_COMBINE_LEN, msg, msg_len, NULL, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int p2prng_combine_update(uint8_t out_hash[P2PRNG_COMBINE_LEN], const uint8_t prev_hash[P2PRNG_COMBINE_LEN], const uint8_t* msg, uint32_t msg_len) { | ||||||
|  | 	// either combine msg and hash, or use streaming interface | ||||||
|  |  | ||||||
|  | 	/*alignas(64)*/ crypto_generichash_state state; | ||||||
|  |  | ||||||
|  | 	// TODO: we could use the first part as key here, should be functionally identical | ||||||
|  | 	// or we hardcode a custom key here, mostly for vanity | ||||||
|  | 	int res = crypto_generichash_init(&state, NULL, 0, P2PRNG_COMBINE_LEN); | ||||||
|  | 	if (res != 0) { | ||||||
|  | 		return res; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// H(msg || Hprev) | ||||||
|  |  | ||||||
|  | 	// first msg | ||||||
|  | 	res = crypto_generichash_update(&state, msg, msg_len); | ||||||
|  | 	if (res != 0) { | ||||||
|  | 		return res; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// then hash from prev round | ||||||
|  | 	res = crypto_generichash_update(&state, prev_hash, P2PRNG_COMBINE_LEN); | ||||||
|  | 	if (res != 0) { | ||||||
|  | 		return res; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return crypto_generichash_final(&state, out_hash, P2PRNG_COMBINE_LEN); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int p2prng_gen_and_auth(uint8_t out_rng[P2PRNG_LEN], uint8_t out_key[P2PRNG_MAC_KEY_LEN], uint8_t out_mac[P2PRNG_MAC_LEN], const uint8_t* is, uint32_t is_len) { | ||||||
|  | 	// generate a (hopefully) cryptogrpahiclly random number | ||||||
|  | 	randombytes_buf(out_rng, P2PRNG_LEN); | ||||||
|  |  | ||||||
|  | 	// combine IS into rng | ||||||
|  | 	int res = p2prng_combine_update(out_rng, out_rng, is, is_len); | ||||||
|  | 	if (res != 0) { | ||||||
|  | 		return res; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return p2prng_auth_create(out_key, out_mac, out_rng, P2PRNG_LEN); | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								src/p2prng.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/p2prng.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | #ifndef P2PRNG_H | ||||||
|  | #define P2PRNG_H | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | // # generate random number and mac | ||||||
|  | // IS should include all peers participating, ideally with a unique id | ||||||
|  | // | ||||||
|  | // usage example: | ||||||
|  | //   uint8_t self_rng[P2PRNG_LEN]; | ||||||
|  | //   uint8_t self_key[P2PRNG_MAC_KEY_LEN]; | ||||||
|  | //   p2prng_gen_and_auth(self_rng, self_key, self_mac, is, is_len); | ||||||
|  | //   // wait for all other macs to arrive <here> | ||||||
|  | //   for (int i = 0; i < peer_count; i++) { | ||||||
|  | //       if (p2prng_auth_verify(peer_mac_key[i], peer_mac[i], peer_msgs[i], peer_msg_len[i]) != 0) { | ||||||
|  | //           // validation error, optionally rerequest | ||||||
|  | //           exit(1); | ||||||
|  | //       } | ||||||
|  | //   } | ||||||
|  | //   // proceed with rng combining | ||||||
|  |  | ||||||
|  | // # combine the random numbers and IS | ||||||
|  | // call with IS last | ||||||
|  | // | ||||||
|  | // usage example: | ||||||
|  | //   uint8_t final_hash[P2PRNG_COMBINE_LEN]; | ||||||
|  | //   p2prng_combine_init(final_hash, peer_msgs[0], peer_msg_len[0]); | ||||||
|  | //   for (int i = 1; i < peer_count; i++) { | ||||||
|  | //       p2prng_combine_update(final_hash, final_hash, peer_msgs[i], peer_msg_len[i]); | ||||||
|  | //   } | ||||||
|  | //   p2prng_combine_update(final_hash, final_hash, is, is_len); | ||||||
|  |  | ||||||
|  | #define P2PRNG_LEN 32u | ||||||
|  | #define P2PRNG_MAC_KEY_LEN 32u | ||||||
|  | #define P2PRNG_MAC_LEN 32u | ||||||
|  | #define P2PRNG_COMBINE_LEN 32u | ||||||
|  |  | ||||||
|  | // TODO: merge key into msg | ||||||
|  | int p2prng_auth_create(uint8_t out_key[P2PRNG_MAC_KEY_LEN], uint8_t out_mac[P2PRNG_MAC_LEN], const uint8_t* msg, uint32_t msg_len); | ||||||
|  | int p2prng_auth_verify(const uint8_t key[P2PRNG_MAC_KEY_LEN], const uint8_t mac[P2PRNG_MAC_LEN], const uint8_t* msg, uint32_t msg_len); | ||||||
|  |  | ||||||
|  | int p2prng_combine_init(uint8_t out_hash[P2PRNG_COMBINE_LEN], const uint8_t* msg, uint32_t msg_len); | ||||||
|  | int p2prng_combine_update(uint8_t out_hash[P2PRNG_COMBINE_LEN], const uint8_t prev_hash[P2PRNG_COMBINE_LEN], const uint8_t* msg, uint32_t msg_len); | ||||||
|  |  | ||||||
|  | // helper that: | ||||||
|  | // - generates the random number (msg) | ||||||
|  | // - calls p2prng_auth_create() | ||||||
|  | int p2prng_gen_and_auth(uint8_t out_rng[P2PRNG_LEN], uint8_t out_key[P2PRNG_MAC_KEY_LEN], uint8_t out_mac[P2PRNG_MAC_LEN], const uint8_t* is, uint32_t is_len); | ||||||
|  |  | ||||||
|  | #endif // P2PRNG_H | ||||||
		Reference in New Issue
	
	Block a user