#include "geocaching/protocol/cmp_writer.h" #include "hostlink/identity_restore_request.h" #include #include int main() { using namespace hostlink::management; using geocaching::protocol::CmpWriter; std::array pub{}, signature{}; std::array priv{}; std::array seed{}; seed.fill(17); pub.fill(3); priv.fill(4); ed25519_create_keypair(pub.data() + 32, priv.data() + 32, seed.data()); std::array hash{}; hash.fill(9); std::array payload{}; CmpWriter p(payload.data(), payload.size()); assert(p.array(8) && p.unsignedInteger(1) && p.text("trailmate.identity.backup.v1") && p.unsignedInteger(0) && p.binary({pub.data(), 64}) && p.binary({priv.data(), 96}) && p.binary({hash.data(), 16}) && p.binary({hash.data(), 16}) && p.unsignedInteger(3)); std::array work{}; constexpr char domain[] = "TrailMate.Identity.Backup.v1"; std::memcpy(work.data(), domain, sizeof(domain)); std::memcpy(work.data() + sizeof(domain), payload.data(), p.size()); ed25519_sign(signature.data(), work.data(), sizeof(domain) + p.size(), pub.data() + 32, priv.data() + 32); std::array request{}; CmpWriter writer(request.data(), request.size()); assert(writer.array(5) && writer.unsignedInteger(7) && writer.binary({pub.data(), 64}) && writer.binary({payload.data(), p.size()}) && writer.binary({signature.data(), 64})); const size_t length = writer.size() + 1; request[length - 1] = 0xc3; IdentityRestoreView view; assert(parseIdentityRestoreRequest({request.data(), length}, view) == Status::Ok); assert(view.expected_generation == 7 && view.backup_generation == 3 && view.private_key.size == 96); assert(verifyIdentityRestoreSignature(view, work.data(), work.size())); for (size_t i = 0; i < sizeof(domain) + p.size(); ++i) assert(work[i] == 0); const_cast(view.signature.data)[0] ^= 1; assert(!verifyIdentityRestoreSignature(view, work.data(), work.size())); const_cast(view.signature.data)[0] ^= 1; assert(!verifyIdentityRestoreSignature(view, const_cast(view.payload.data), 352)); request[length - 1] = 0xc2; assert(parseIdentityRestoreRequest({request.data(), length}, view) == Status::Unauthorized && view.private_key.data == nullptr); request[length - 1] = 0xc3; request[length] = 0; assert(parseIdentityRestoreRequest({request.data(), length + 1}, view) == Status::InvalidField); for (size_t i = 0; i < length; ++i) assert(parseIdentityRestoreRequest({request.data(), i}, view) != Status::Ok); }