{"id":21717423,"url":"https://github.com/sandsmark/qt-rappor-client","last_synced_at":"2026-04-30T19:31:56.989Z","repository":{"id":66625121,"uuid":"268892552","full_name":"sandsmark/qt-rappor-client","owner":"sandsmark","description":"C++ implementation of privacy preserving metrics reporting using Rappor (Randomized Aggregatable Privacy Preserving Ordinal Responses), with Qt integration","archived":false,"fork":false,"pushed_at":"2020-12-10T15:28:32.000Z","size":122,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-03T20:16:02.480Z","etag":null,"topics":["cpp","cpp17","metrics","metrics-gathering","metrics-library","privacy","privacy-by-design","privacy-preserving","privacy-protection","qt","qt6","rappor"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandsmark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-02T19:40:23.000Z","updated_at":"2022-11-04T09:17:14.000Z","dependencies_parsed_at":"2023-02-25T22:30:39.189Z","dependency_job_id":null,"html_url":"https://github.com/sandsmark/qt-rappor-client","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sandsmark/qt-rappor-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandsmark%2Fqt-rappor-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandsmark%2Fqt-rappor-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandsmark%2Fqt-rappor-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandsmark%2Fqt-rappor-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandsmark","download_url":"https://codeload.github.com/sandsmark/qt-rappor-client/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandsmark%2Fqt-rappor-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32475191,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"ssl_error","status_checked_at":"2026-04-30T13:12:06.837Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","cpp17","metrics","metrics-gathering","metrics-library","privacy","privacy-by-design","privacy-preserving","privacy-protection","qt","qt6","rappor"],"created_at":"2024-11-26T01:17:40.968Z","updated_at":"2026-04-30T19:31:56.984Z","avatar_url":"https://github.com/sandsmark.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"qt-rappor-client\n================\n\n\nA fork of the reference C++ implementation of RAPPOR, as the upstream reference\nimplementation repo is dead.\n\nThe other major forks/implementations are:\n    - https://chromium.googlesource.com/chromium/src/+/master/components/rappor/\n    - https://fuchsia.googlesource.com/cobalt (latest release doesn't have the server side components anymore, though you can check out the tags)\n\nDependencies\n============\n\n    - Git\n    - CMake\n    - C++ compiler\n    - Qt\n\n\n\nRAPPOR\n======\n\nIf you want the dirty details the published paper is here:\nhttps://doi.org/10.1145/2660267.2660348\n\nA more high-level description from the Chromium project is available here:\nhttps://www.chromium.org/developers/design-documents/rappor\n\n\nOriginal README follows:\n------------------------\n\n\nRAPPOR C++ Client\n=================\n\nWe provide both a low level and high level client API.  The low level API\nimplements just the RAPPOR encoding algorithm on strings, with few\ndependencies.\n\nThe high level API provides wrappers that bundle encoded values into Protocol\nBuffer messages.\n\nEncoder\n-------\n\nThe low level API is `Encoder`.  You instantiatate it with RAPPOR encoding\nparameters and application dependencies.  It has a method `EncodeString()` that\ntakes an input string (no other types), sets an output parameter of type\n`rappor::Bits`, and returns success or failure.\n\n```cpp\n#include \u003ccassert\u003e  // assert\n\n#include \"qt-rappor-client/encoder.h\"\n#include \"qt-rappor-client/qt_hash_impl.h\"\n#include \"qt-rappor-client/std_rand_impl.h\"\n\nint main(int argc, char** argv) {\n  // Suppress unused variable warnings\n  (void) argc;\n  (void) argv;\n\n  rappor::Deps deps(rappor::Md5, \"client-secret\", rappor::HmacSha256,\n                    std::make_shared\u003crappor::StdRand\u003e());\n  rappor::Params params(32,    // num_bits (k)\n                        2,     // num_hashes (h)\n                        128,   // num_cohorts (m)\n                        0.25,  // probability f for PRR\n                        0.75,  // probability p for IRR\n                        0.5);  // probability q for IRR\n\n  const char* encoder_id = \"metric-name\";\n  rappor::Encoder encoder(encoder_id, params, deps);\n\n  // Now use it to encode values.  The 'out' value can be sent over the\n  // network.\n  rappor::Bits out;\n  assert(encoder.EncodeString(\"foo\", \u0026out));  // returns false on error\n  printf(\"'foo' encoded with RAPPOR: %0x, cohort %d\\n\", out, encoder.cohort());\n\n  // Raw bits\n  assert(encoder.EncodeBits(0x123, \u0026out));  // returns false on error\n  printf(\"0x123 encoded with RAPPOR: %0x, cohort %d\\n\", out, encoder.cohort());\n}\n```\n\nDependencies\n------------\n\n`rappor::Deps` is a struct-like object that holds the dependencies needed by\nthe API.\n\nThe application must provide the following values:\n\n- cohort: An integer between 0 and `num_cohorts - 1`.  Each value is assigned\n  with equal probability to a client process.\n- client_secret: A persistent client secret (used for deterministic randomness\n  in the PRR, i.e. \"memoization\" requirement).\n- hash_func - string hash function implementation (e.g. MD5)\n- hmac_func - HMAC-SHA256 implementation\n- irr_rand - randomness for the IRR\n\nWe provide an implementation of `hash_func` and `hmac_func` and using OpenSSL.\nIf your application already has a different implementation of these functions,\nyou can implement the `HashFunc` and HmacFunc` interfaces.\n\nWe provide two example implementations of `irr_rand`: one based on libc\n`rand()` (insecure, for demo only), and one based on Unix `/dev/urandom`.\n\nError Handling\n--------------\n\nNote that incorrect usage of the `SimpleEncoder` and `Protobuf` constructors\nmay cause *runtime assertions* (using `assert()`).  For example, if\nParams.num\\_bits is more than 32, the process will crash.\n\nEncoders should be initialized at application startup, with constant\nparameters, so this type of error should be seen early.\n\nThe various `Encode()` members do *not* raise assertions.  If those are used\nincorrectly, then the return value will be `false` to indicate an error.  These\nfailures should be handled by the application.\n\nMemory Management\n-----------------\n\nThe `Encoder` instances contain pointers to `Params` and `Deps` instances, but\ndon't own them.  In the examples, all instances live the stack of `main()`, so\nyou don't have to worry about them being destroyed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandsmark%2Fqt-rappor-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandsmark%2Fqt-rappor-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandsmark%2Fqt-rappor-client/lists"}