implementation of the cryptographic primitives
This commit is contained in:
parent
839c516add
commit
dd47e44254
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
|
Loading…
Reference in New Issue
Block a user