Commit 62884953 authored by Bernard van Gastel's avatar Bernard van Gastel
Browse files

Introduces an easy to use general PEP API; added CLI interface for that easy PEP CLI.

parent 82cdbb8b
...@@ -177,10 +177,13 @@ endif() ...@@ -177,10 +177,13 @@ endif()
add_library(lib${PROJECT_NAME} src/base.cpp src/core.cpp src/zkp.cpp) add_library(lib${PROJECT_NAME} src/base.cpp src/core.cpp src/zkp.cpp src/libpep.cpp)
target_include_directories(lib${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(lib${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(lib${PROJECT_NAME} extlib) target_link_libraries(lib${PROJECT_NAME} extlib)
add_executable(lib${PROJECT_NAME}cli src/cli.cpp)
target_link_libraries(lib${PROJECT_NAME}cli lib${PROJECT_NAME})
if (TEST) if (TEST)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/ext/catch2/contrib) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/ext/catch2/contrib)
ENABLE_TESTING() ENABLE_TESTING()
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#define ENSURE_TEXT(e, text) ((e) ? (void)0 : CrashAssert(__func__, __FILE__, __LINE__, #e, text)) #define ENSURE_TEXT(e, text) ((e) ? (void)0 : CrashAssert(__func__, __FILE__, __LINE__, #e, text))
extern "C" [[noreturn]] void CrashAssert(const char* func, const char* file, int line, const char* condition, const char* explanation = nullptr); extern "C" [[noreturn]] void CrashAssert(const char* func, const char* file, int line, const char* condition, const char* explanation = nullptr);
namespace radboud {
namespace pep { namespace pep {
struct GroupElement; struct GroupElement;
...@@ -167,5 +166,4 @@ void FromHex(uint8_t (&out)[N], std::string_view in) { ...@@ -167,5 +166,4 @@ void FromHex(uint8_t (&out)[N], std::string_view in) {
} }
} }
}
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "base.h" #include "base.h"
namespace radboud {
namespace pep { namespace pep {
struct ElGamal { struct ElGamal {
...@@ -38,4 +37,3 @@ ElGamal Reshuffle(const ElGamal& in, const Scalar& n); ...@@ -38,4 +37,3 @@ ElGamal Reshuffle(const ElGamal& in, const Scalar& n);
ElGamal RKS(const ElGamal& in, const Scalar& k, const Scalar& n); ElGamal RKS(const ElGamal& in, const Scalar& k, const Scalar& n);
} }
}
// Author: Bernard van Gastel // Author: Bernard van Gastel
#include "zkp.h" #include "zkp.h"
namespace pep {
using GlobalPublicKey = GroupElement;
using GlobalSecretKey = Scalar;
using GlobalEncryptedPseudonym = ElGamal;
using LocalEncryptedPseudonym = ElGamal;
using LocalPseudonym = GroupElement;
using LocalDecryptionKey = Scalar;
std::tuple<GlobalPublicKey, GlobalSecretKey> GenerateGlobalKeys();
GlobalEncryptedPseudonym GeneratePseudonym(const std::string& identity, const GlobalPublicKey& pk);
LocalEncryptedPseudonym ConvertToLocalPseudonym(GlobalEncryptedPseudonym p, const std::string& secret, const std::string& decryptionContext, const std::string& pseudonimisationContext);
LocalDecryptionKey MakeLocalDecryptionKey(GlobalSecretKey k, const std::string& secret, const std::string& decryptionContext);
LocalPseudonym DecryptLocalPseudonym(LocalEncryptedPseudonym p, LocalDecryptionKey k);
GlobalEncryptedPseudonym RerandomizeGlobal(const GlobalEncryptedPseudonym& p);
LocalEncryptedPseudonym RerandomizeLocal(const LocalEncryptedPseudonym& p);
}
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include "core.h" #include "core.h"
namespace radboud {
namespace pep { namespace pep {
// offline Schnorr proof // offline Schnorr proof
...@@ -77,4 +76,3 @@ ProvedRKS ProveRKS(const ElGamal& in, const Scalar& k, const Scalar& n); ...@@ -77,4 +76,3 @@ ProvedRKS ProveRKS(const ElGamal& in, const Scalar& k, const Scalar& n);
GroupElement RekeyByPublicKey(const ProvedRKS& in); GroupElement RekeyByPublicKey(const ProvedRKS& in);
} }
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "sodium.h" #include "sodium.h"
using namespace radboud::pep; using namespace pep;
extern "C" [[noreturn]] void CrashAssert(const char* func, const char* file, int line, const char* condition, const char* explanation) { extern "C" [[noreturn]] void CrashAssert(const char* func, const char* file, int line, const char* condition, const char* explanation) {
fprintf(stderr, "asserton '%s' violated: %s [%s:%i] %s\n", condition, func, file, line, explanation); fprintf(stderr, "asserton '%s' violated: %s [%s:%i] %s\n", condition, func, file, line, explanation);
...@@ -123,7 +123,6 @@ GroupElement GroupElement::Random() { ...@@ -123,7 +123,6 @@ GroupElement GroupElement::Random() {
crypto_core_ristretto255_random(r.value); crypto_core_ristretto255_random(r.value);
return r; return r;
} }
namespace radboud {
namespace pep { namespace pep {
GroupElement operator+(const GroupElement& lhs, const GroupElement& rhs) { GroupElement operator+(const GroupElement& lhs, const GroupElement& rhs) {
...@@ -238,5 +237,4 @@ void FromHex(uint8_t* out, size_t out_len, std::string_view in) { ...@@ -238,5 +237,4 @@ void FromHex(uint8_t* out, size_t out_len, std::string_view in) {
} }
} }
}
// Author: Bernard van Gastel
#include "libpep.h"
#include <iostream>
int main(int argc, char** argv) {
std::string subcommand;
if (argc >= 2)
subcommand = argv[1];
try {
if (subcommand == "generate-global-keys") {
auto [pk, sk] = pep::GenerateGlobalKeys();
std::cerr << "Public global key: " << std::endl;
std::cout << pk.hex() << std::endl;
std::cerr << "Secret global key: " << std::endl;
std::cout << sk.hex() << std::endl;
return 0;
}
if (subcommand == "generate-pseudonym") {
if (argc != 4) {
std::cerr << "wrong number of arguments" << std::endl;
return -1;
}
std::string identity = argv[2];
auto pk = pep::GlobalPublicKey::FromHex(argv[3]);
auto local = pep::GeneratePseudonym(identity, pk);
std::cerr << local.hex() << std::endl;
return 0;
}
if (subcommand == "convert-to-local-pseudonym") {
if (argc != 6) {
std::cerr << "wrong number of arguments" << std::endl;
return -1;
}
auto p = pep::GlobalEncryptedPseudonym::FromHex(argv[2]);
std::string serverSecret = argv[3];
std::string decryptionContext = argv[4];
std::string pContext = argv[5];
auto local = pep::ConvertToLocalPseudonym(p, serverSecret, decryptionContext, pContext);
local = pep::RerandomizeLocal(local);
std::cerr << local.hex() << std::endl;
return 0;
}
if (subcommand == "make-local-decryption-key") {
if (argc != 5) {
std::cerr << "wrong number of arguments" << std::endl;
return -1;
}
auto sk = pep::GlobalSecretKey::FromHex(argv[2]);
std::string serverSecret = argv[3];
std::string decryptionContext = argv[4];
auto localSk = pep::MakeLocalDecryptionKey(sk, serverSecret, decryptionContext);
std::cerr << localSk.hex() << std::endl;
return 0;
}
if (subcommand == "decrypt-local-pseudonym") {
if (argc != 4) {
std::cerr << "wrong number of arguments" << std::endl;
return -1;
}
auto local = pep::LocalEncryptedPseudonym::FromHex(argv[2]);
auto sk = pep::LocalDecryptionKey::FromHex(argv[3]);
auto p = pep::DecryptLocalPseudonym(local, sk);
std::cerr << p.hex() << std::endl;
return 0;
}
} catch (std::exception& e) {
std::cerr << "got exception: " << std::endl;
std::cerr << e.what() << std::endl;
return -1;
}
std::cerr << argv[0] << " expects at least one subcommand: " << std::endl;
std::cerr << std::endl;
std::cerr << argv[0] << " generate-global-keys" << std::endl;
std::cerr << " Outputs a public key and a secret key." << std::endl;
std::cerr << std::endl;
std::cerr << argv[0] << " generate-pseudonym [identity] [global-public-key]" << std::endl;
std::cerr << " Generates an encrypted global pseudonym." << std::endl;
std::cerr << std::endl;
std::cerr << argv[0] << " convert-to-local-pseudonym [pseudonym] [server-secret] [decryption-context] [pseudonymisation-context]" << std::endl;
std::cerr << " Converts a global encrypted pseudonym to a local encrypted pseudonym, decryptable by anybody that has the secret key as generated by make-local-decryption-key with the same decryption-context. The pseudonyms will be stable if the same pseudonymisation context is given. Server secret is a random string (so the pseudonymisation and decryption factors are not guessable)." << std::endl;
std::cerr << std::endl;
std::cerr << argv[0] << " make-local-decryption-key [global-secret-key] [server-secret] [decryption-context]" << std::endl;
std::cerr << " Creates a key that a party can use to decrypt an encrypted local pseudonym." << std::endl;
std::cerr << std::endl;
std::cerr << argv[0] << " decrypt-local-pseudonym [pseudonym] [local-decryption-key]" << std::endl;
std::cerr << " Decrypts the local encrypted pseudonym with a local decryption key as generated by make-local-decryption-key." << std::endl;
std::cerr << std::endl;
return -1;
}
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
#include "core.h" #include "core.h"
using namespace radboud::pep; using namespace pep;
radboud::pep::ElGamal::ElGamal(GroupElement _B, const GroupElement& _C, const GroupElement& _Y) : B(_B), C(_C), Y(_Y) { pep::ElGamal::ElGamal(GroupElement _B, const GroupElement& _C, const GroupElement& _Y) : B(_B), C(_C), Y(_Y) {
} }
std::string ElGamal::hex() const { std::string ElGamal::hex() const {
...@@ -20,16 +20,16 @@ ElGamal ElGamal::FromHex(std::string_view view) { ...@@ -20,16 +20,16 @@ ElGamal ElGamal::FromHex(std::string_view view) {
retval.Y = GroupElement::FromHex(view.substr(128, 64)); retval.Y = GroupElement::FromHex(view.substr(128, 64));
return retval; return retval;
} }
bool radboud::pep::ElGamal::operator==(const ElGamal& rhs) const { bool pep::ElGamal::operator==(const ElGamal& rhs) const {
return B == rhs.B && C == rhs.C && Y == rhs.Y; return B == rhs.B && C == rhs.C && Y == rhs.Y;
} }
bool radboud::pep::ElGamal::operator!=(const ElGamal& rhs) const { bool pep::ElGamal::operator!=(const ElGamal& rhs) const {
return B != rhs.B || C != rhs.C || Y != rhs.Y; return B != rhs.B || C != rhs.C || Y != rhs.Y;
} }
// encrypt message M using public key Y // encrypt message M using public key Y
ElGamal radboud::pep::Encrypt(const GroupElement& M, const GroupElement& Y) { ElGamal pep::Encrypt(const GroupElement& M, const GroupElement& Y) {
auto r = Scalar::Random(); auto r = Scalar::Random();
EXPECT(!r.zero()); // Random() does never return a zero scalar EXPECT(!r.zero()); // Random() does never return a zero scalar
ENSURE(!Y.zero()); // we should not encrypt anything with an empty public key, as this will result in plain text send over the line ENSURE(!Y.zero()); // we should not encrypt anything with an empty public key, as this will result in plain text send over the line
...@@ -37,7 +37,7 @@ ElGamal radboud::pep::Encrypt(const GroupElement& M, const GroupElement& Y) { ...@@ -37,7 +37,7 @@ ElGamal radboud::pep::Encrypt(const GroupElement& M, const GroupElement& Y) {
} }
// decrypt encrypted ElGamal tuple with secret key y // decrypt encrypted ElGamal tuple with secret key y
GroupElement radboud::pep::Decrypt(const ElGamal& in, const Scalar& y) { GroupElement pep::Decrypt(const ElGamal& in, const Scalar& y) {
return in.C - y * in.B; return in.C - y * in.B;
} }
...@@ -46,21 +46,21 @@ ElGamal RerandomizeY(const ElGamal& in, const Scalar& s) { ...@@ -46,21 +46,21 @@ ElGamal RerandomizeY(const ElGamal& in, const Scalar& s) {
} }
// randomize the encryption // randomize the encryption
ElGamal radboud::pep::Rerandomize(const ElGamal& in, const Scalar& s) { ElGamal pep::Rerandomize(const ElGamal& in, const Scalar& s) {
return {s * G + in.B, s * in.Y + in.C, in.Y}; return {s * G + in.B, s * in.Y + in.C, in.Y};
} }
// make it decryptable with another key k*y (with y the original private key) // make it decryptable with another key k*y (with y the original private key)
ElGamal radboud::pep::Rekey(const ElGamal& in, const Scalar& k) { ElGamal pep::Rekey(const ElGamal& in, const Scalar& k) {
return {in.B / k, in.C, k * in.Y}; return {in.B / k, in.C, k * in.Y};
} }
// adjust the encrypted cypher text to be n*M (with M the original text being encrypted) // adjust the encrypted cypher text to be n*M (with M the original text being encrypted)
ElGamal radboud::pep::Reshuffle(const ElGamal& in, const Scalar& n) { ElGamal pep::Reshuffle(const ElGamal& in, const Scalar& n) {
return {n * in.B, n * in.C, in.Y}; return {n * in.B, n * in.C, in.Y};
} }
// combination of Rekey(k) and Reshuffle(n) // combination of Rekey(k) and Reshuffle(n)
ElGamal radboud::pep::RKS(const ElGamal& in, const Scalar& k, const Scalar& n) { ElGamal pep::RKS(const ElGamal& in, const Scalar& k, const Scalar& n) {
return {(n / k) * in.B, n * in.C, k * in.Y}; return {(n / k) * in.B, n * in.C, k * in.Y};
} }
// Author: Bernard van Gastel
#include "libpep.h"
using namespace pep;
std::tuple<GlobalPublicKey, GlobalSecretKey> pep::GenerateGlobalKeys() {
auto secretKey = Scalar::Random();
auto publicKey = secretKey * G;
return {publicKey, secretKey};
}
GlobalEncryptedPseudonym pep::GeneratePseudonym(const std::string& identity, const GlobalPublicKey& pk) {
HashSHA512 hash;
SHA512(hash, identity);
auto p = GroupElement::FromHash(hash);
return Encrypt(p, pk);
}
Scalar MakeFactor(const std::string& secret, const std::string& context) {
HashSHA512 uhash;
SHA512(uhash, secret, "|", context);
return Scalar::FromHash(uhash);
}
LocalEncryptedPseudonym pep::ConvertToLocalPseudonym(GlobalEncryptedPseudonym p, const std::string& secret, const std::string& decryptionContext, const std::string& pseudonimisationContext) {
Scalar u = MakeFactor(secret, pseudonimisationContext);
Scalar t = MakeFactor(secret, decryptionContext);
return RKS(p, t, u);
}
LocalDecryptionKey pep::MakeLocalDecryptionKey(GlobalSecretKey k, const std::string& secret, const std::string& decryptionContext) {
Scalar t = MakeFactor(secret, decryptionContext);
return t * k;
}
LocalPseudonym pep::DecryptLocalPseudonym(LocalEncryptedPseudonym p, LocalDecryptionKey k) {
return Decrypt(p, k);
}
GlobalEncryptedPseudonym pep::RerandomizeGlobal(const GlobalEncryptedPseudonym& p) {
return Rerandomize(p, Scalar::Random());
}
LocalEncryptedPseudonym pep::RerandomizeLocal(const LocalEncryptedPseudonym& p) {
return Rerandomize(p, Scalar::Random());
}
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
#include "zkp.h" #include "zkp.h"
using namespace radboud::pep; using namespace pep;
std::tuple<GroupElement,Proof> radboud::pep::CreateProof(const Scalar& a /*secret*/, const GroupElement& M /*public*/) { std::tuple<GroupElement,Proof> pep::CreateProof(const Scalar& a /*secret*/, const GroupElement& M /*public*/) {
Scalar r = Scalar::Random(); Scalar r = Scalar::Random();
GroupElement A = a * G; GroupElement A = a * G;
...@@ -24,7 +24,7 @@ std::tuple<GroupElement,Proof> radboud::pep::CreateProof(const Scalar& a /*secre ...@@ -24,7 +24,7 @@ std::tuple<GroupElement,Proof> radboud::pep::CreateProof(const Scalar& a /*secre
return {A, {N, C1, C2, s}}; return {A, {N, C1, C2, s}};
} }
[[nodiscard]] bool radboud::pep::VerifyProof(const GroupElement& A, const GroupElement& M, const GroupElement& N, const GroupElement& C1, const GroupElement& C2, const Scalar& s) { [[nodiscard]] bool pep::VerifyProof(const GroupElement& A, const GroupElement& M, const GroupElement& N, const GroupElement& C1, const GroupElement& C2, const Scalar& s) {
if (!A.valid() || !M.valid() || !N.valid() || !C1.valid() || !C2.valid() || !s.valid()) if (!A.valid() || !M.valid() || !N.valid() || !C1.valid() || !C2.valid() || !s.valid())
return false; return false;
HashSHA512 hash; HashSHA512 hash;
...@@ -40,80 +40,80 @@ std::tuple<GroupElement,Proof> radboud::pep::CreateProof(const Scalar& a /*secre ...@@ -40,80 +40,80 @@ std::tuple<GroupElement,Proof> radboud::pep::CreateProof(const Scalar& a /*secre
&& s * M == e*N + C2; && s * M == e*N + C2;
} }
[[nodiscard]] bool radboud::pep::VerifyProof(const GroupElement& A, const GroupElement& M, const Proof& p) { [[nodiscard]] bool pep::VerifyProof(const GroupElement& A, const GroupElement& M, const Proof& p) {
return VerifyProof(A, M, p.N, p.C1, p.C2, p.s); return VerifyProof(A, M, p.N, p.C1, p.C2, p.s);
} }
Signature radboud::pep::Sign(const GroupElement& message, const Scalar& secretKey) { Signature pep::Sign(const GroupElement& message, const Scalar& secretKey) {
auto p = CreateProof(secretKey, message); auto p = CreateProof(secretKey, message);
return std::get<1>(p); return std::get<1>(p);
} }
[[nodiscard]] bool radboud::pep::Verify(const GroupElement& message, const Signature& p, const GroupElement& publicKey) { [[nodiscard]] bool pep::Verify(const GroupElement& message, const Signature& p, const GroupElement& publicKey) {
return VerifyProof(publicKey, message, p.N, p.C1, p.C2, p.s); return VerifyProof(publicKey, message, p.N, p.C1, p.C2, p.s);
} }
ProvedRerandomize radboud::pep::ProveRerandomize(const ElGamal& in, const Scalar& s) { ProvedRerandomize pep::ProveRerandomize(const ElGamal& in, const Scalar& s) {
// Rerandomize is normally {s * G + in.b, s*in.y + in.c, in.y}; // Rerandomize is normally {s * G + in.b, s*in.y + in.c, in.y};
return CreateProof(s, in.Y); return CreateProof(s, in.Y);
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyRerandomize(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& S, const Proof& py) { [[nodiscard]] std::optional<ElGamal> pep::VerifyRerandomize(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& S, const Proof& py) {
// slightly different than the others, as we reuse the structure of a standard proof to reconstruct the Rerandomize operation after sending // slightly different than the others, as we reuse the structure of a standard proof to reconstruct the Rerandomize operation after sending
return B.valid() && C.valid() && VerifyProof(S, Y, py) ? return B.valid() && C.valid() && VerifyProof(S, Y, py) ?
ElGamal{S + B, py.value() + C, Y} : std::optional<ElGamal>(); ElGamal{S + B, py.value() + C, Y} : std::optional<ElGamal>();
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyRerandomize(const ElGamal& in, const ProvedRerandomize& p) { [[nodiscard]] std::optional<ElGamal> pep::VerifyRerandomize(const ElGamal& in, const ProvedRerandomize& p) {
return VerifyRerandomize(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p)); return VerifyRerandomize(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p));
} }
// adjust the encrypted cypher text to be n*M (with M the original text being encrypted) // adjust the encrypted cypher text to be n*M (with M the original text being encrypted)
ProvedReshuffle radboud::pep::ProveReshuffle(const ElGamal& in, const Scalar& n) { ProvedReshuffle pep::ProveReshuffle(const ElGamal& in, const Scalar& n) {
// Reshuffle is normally {n * in.b, n * in.c, in.y}; // Reshuffle is normally {n * in.b, n * in.c, in.y};
// NOTE: can be optimised a bit, by fusing the two CreateProofs (because same n is used) // NOTE: can be optimised a bit, by fusing the two CreateProofs (because same n is used)
auto [AB, pb] = CreateProof(n, in.B); auto [AB, pb] = CreateProof(n, in.B);
auto [AC, pc] = CreateProof(n, in.C); auto [AC, pc] = CreateProof(n, in.C);
return {AB, pb, AC, pc}; return {AB, pb, AC, pc};
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyReshuffle(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& AB, const Proof& pb, const GroupElement& AC, const Proof& pc) { [[nodiscard]] std::optional<ElGamal> pep::VerifyReshuffle(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& AB, const Proof& pb, const GroupElement& AC, const Proof& pc) {
return VerifyProof(AB, B, pb) && VerifyProof(AC, C, pc) && Y.valid() ? return VerifyProof(AB, B, pb) && VerifyProof(AC, C, pc) && Y.valid() ?
ElGamal{pb.value(), pc.value(), Y} : std::optional<ElGamal>(); ElGamal{pb.value(), pc.value(), Y} : std::optional<ElGamal>();
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyReshuffle(const ElGamal& in, const ProvedReshuffle& p) { [[nodiscard]] std::optional<ElGamal> pep::VerifyReshuffle(const ElGamal& in, const ProvedReshuffle& p) {
return VerifyReshuffle(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p), std::get<2>(p), std::get<3>(p)); return VerifyReshuffle(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p), std::get<2>(p), std::get<3>(p));
} }
// adjust the encrypted cypher text to be n*M (with M the original text being encrypted) // adjust the encrypted cypher text to be n*M (with M the original text being encrypted)
ProvedRekey radboud::pep::ProveRekey(const ElGamal& in, const Scalar& k) { ProvedRekey pep::ProveRekey(const ElGamal& in, const Scalar& k) {
// Rekey is normmaly {in.b/k, in.c, k*in.y}; // Rekey is normmaly {in.b/k, in.c, k*in.y};
auto [AB, pb] = CreateProof(k.invert(), in.B); auto [AB, pb] = CreateProof(k.invert(), in.B);
auto [AY, py] = CreateProof(k, in.Y); auto [AY, py] = CreateProof(k, in.Y);
return {AB, pb, AY, py}; return {AB, pb, AY, py};
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyRekey(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& AB, const Proof& pb, const GroupElement& AY, const Proof& py) { [[nodiscard]] std::optional<ElGamal> pep::VerifyRekey(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& AB, const Proof& pb, const GroupElement& AY, const Proof& py) {
return VerifyProof(AB, B, pb) && C.valid() && VerifyProof(AY, Y, py) ? return VerifyProof(AB, B, pb) && C.valid() && VerifyProof(AY, Y, py) ?
ElGamal{pb.value(), C, py.value()} : std::optional<ElGamal>(); ElGamal{pb.value(), C, py.value()} : std::optional<ElGamal>();
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyRekey(const ElGamal& in, const ProvedRekey& p) { [[nodiscard]] std::optional<ElGamal> pep::VerifyRekey(const ElGamal& in, const ProvedRekey& p) {
return VerifyRekey(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p), std::get<2>(p), std::get<3>(p)); return VerifyRekey(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p), std::get<2>(p), std::get<3>(p));
} }
GroupElement radboud::pep::RekeyByPublicKey(const ProvedRekey& in) { GroupElement pep::RekeyByPublicKey(const ProvedRekey& in) {
return std::get<2>(in); return std::get<2>(in);
} }
ProvedRKS radboud::pep::ProveRKS(const ElGamal& in, const Scalar& k, const Scalar& n) { ProvedRKS pep::ProveRKS(const ElGamal& in, const Scalar& k, const Scalar& n) {
// RKS is normally {(n / k) * in.B, n * in.C, k * in.Y}; // RKS is normally {(n / k) * in.B, n * in.C, k * in.Y};
return std::tuple_cat(CreateProof(n/k, in.B), CreateProof(n, in.C), CreateProof(k, in.Y)); return std::tuple_cat(CreateProof(n/k, in.B), CreateProof(n, in.C), CreateProof(k, in.Y));
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyRKS(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& AB, const Proof& pb, const GroupElement& AC, const Proof& pc, const GroupElement& AY, const Proof& py) { [[nodiscard]] std::optional<ElGamal> pep::VerifyRKS(const GroupElement& B, const GroupElement& C, const GroupElement& Y, const GroupElement& AB, const Proof& pb, const GroupElement& AC, const Proof& pc, const GroupElement& AY, const Proof& py) {
return VerifyProof(AB, B, pb) && VerifyProof(AC, C, pc) && VerifyProof(AY, Y, py) ? return VerifyProof(AB, B, pb) && VerifyProof(AC, C, pc) && VerifyProof(AY, Y, py) ?
ElGamal{pb.value(), pc.value(), py.value()} : std::optional<ElGamal>(); ElGamal{pb.value(), pc.value(), py.value()} : std::optional<ElGamal>();
} }
[[nodiscard]] std::optional<ElGamal> radboud::pep::VerifyRKS(const ElGamal& in, const ProvedRKS& p) { [[nodiscard]] std::optional<ElGamal> pep::VerifyRKS(const ElGamal& in, const ProvedRKS& p) {
return VerifyRKS(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p), std::get<2>(p), std::get<3>(p), std::get<4>(p), std::get<5>(p)); return VerifyRKS(in.B, in.C, in.Y, std::get<0>(p), std::get<1>(p), std::get<2>(p), std::get<3>(p), std::get<4>(p), std::get<5>(p));
} }
GroupElement radboud::pep::RekeyByPublicKey(const ProvedRKS& in) { GroupElement pep::RekeyByPublicKey(const ProvedRKS& in) {
return std::get<4>(in); return std::get<4>(in);
} }
// Author: Bernard van Gastel // Author: Bernard van Gastel
#include "zkp.h" #include "libpep.h"
#include <limits.h> #include <limits.h>
#include <optional> #include <optional>
...@@ -12,7 +12,7 @@ IGNORE_WARNINGS_START ...@@ -12,7 +12,7 @@ IGNORE_WARNINGS_START
IGNORE_WARNINGS_END IGNORE_WARNINGS_END
namespace { namespace {
using namespace radboud::pep; using namespace pep;
using namespace std::literals; using namespace std::literals;
TEST_CASE("PEP.Base", "[PEP]") {