1*2abb3134SXin LiRAPPOR C++ Client 2*2abb3134SXin Li================= 3*2abb3134SXin Li 4*2abb3134SXin LiWe provide both a low level and high level client API. The low level API 5*2abb3134SXin Liimplements just the RAPPOR encoding algorithm on strings, with few 6*2abb3134SXin Lidependencies. 7*2abb3134SXin Li 8*2abb3134SXin LiThe high level API provides wrappers that bundle encoded values into Protocol 9*2abb3134SXin LiBuffer messages. 10*2abb3134SXin Li 11*2abb3134SXin LiBuild Instructions 12*2abb3134SXin Li------------------ 13*2abb3134SXin Li 14*2abb3134SXin LiYou'll need a C++ compiler, the protobuf compiler, and a library that 15*2abb3134SXin Liimplements common hash functions (e.g. OpenSSL). 16*2abb3134SXin Li 17*2abb3134SXin LiOn Ubuntu or Debian, the protobuf compiler and header files can be installed 18*2abb3134SXin Liwith: 19*2abb3134SXin Li 20*2abb3134SXin Li sudo apt-get install protobuf-compiler libprotobuf-dev 21*2abb3134SXin Li 22*2abb3134SXin LiOpenSSL can be installed with: 23*2abb3134SXin Li 24*2abb3134SXin Li sudo apt-get install libssl-dev 25*2abb3134SXin Li 26*2abb3134SXin LiTest 27*2abb3134SXin Li---- 28*2abb3134SXin Li 29*2abb3134SXin LiAfter installing dependencies, You can test it out easily on your machine: 30*2abb3134SXin Li 31*2abb3134SXin Li ./demo.sh quick-cpp 32*2abb3134SXin Li 33*2abb3134SXin LiThis builds the test harness using a Makefile, and then runs the regtest.sh 34*2abb3134SXin Lisimulation. The last few lines of output will look like this: 35*2abb3134SXin Li 36*2abb3134SXin Li Done running all test instances 37*2abb3134SXin Li Instances succeeded: 1 failed: 0 running: 0 total: 1 38*2abb3134SXin Li Wrote _tmp/cpp/results.html 39*2abb3134SXin Li URL: file:///usr/local/google/home/andychu/git/rappor/_tmp/cpp/results.html 40*2abb3134SXin Li 41*2abb3134SXin LiOpen the HTML file to see a plot and stats. 42*2abb3134SXin Li 43*2abb3134SXin Li 44*2abb3134SXin LiEncoder 45*2abb3134SXin Li------- 46*2abb3134SXin Li 47*2abb3134SXin LiThe low level API is `Encoder`. You instantiatate it with RAPPOR encoding 48*2abb3134SXin Liparameters and application dependencies. It has a method `EncodeString()` that 49*2abb3134SXin Litakes an input string (no other types), sets an output parameter of type 50*2abb3134SXin Li`rappor::Bits`, and returns success or failure. 51*2abb3134SXin Li 52*2abb3134SXin Li```cpp 53*2abb3134SXin Li#include <cassert> 54*2abb3134SXin Li 55*2abb3134SXin Li#include "encoder.h" 56*2abb3134SXin Li#include "openssl_hash_impl.h" 57*2abb3134SXin Li#include "unix_kernel_rand_impl.h" 58*2abb3134SXin Li 59*2abb3134SXin Liint main(int argc, char** argv) { 60*2abb3134SXin Li FILE* fp = fopen("/dev/urandom", "r"); 61*2abb3134SXin Li rappor::UnixKernelRand irr_rand(fp); 62*2abb3134SXin Li 63*2abb3134SXin Li rappor::Deps deps(rappor::Md5, "client-secret", rappor::HmacSha256, 64*2abb3134SXin Li irr_rand); 65*2abb3134SXin Li rappor::Params params(32, // num_bits (k) 66*2abb3134SXin Li 2, // num_hashes (h) 67*2abb3134SXin Li 128, // num_cohorts (m) 68*2abb3134SXin Li 0.25, // probability f for PRR 69*2abb3134SXin Li 0.75, // probability p for IRR 70*2abb3134SXin Li 0.5); // probability q for IRR 71*2abb3134SXin Li 72*2abb3134SXin Li const char* encoder_id = "metric-name"; 73*2abb3134SXin Li rappor::Encoder encoder(encoder_id, params, deps); 74*2abb3134SXin Li 75*2abb3134SXin Li // Now use it to encode values. The 'out' value can be sent over the 76*2abb3134SXin Li // network. 77*2abb3134SXin Li rappor::Bits out; 78*2abb3134SXin Li assert(encoder.EncodeString("foo", &out)); // returns false on error 79*2abb3134SXin Li printf("'foo' encoded with RAPPOR: %0x, cohort %d\n", out, encoder.cohort()); 80*2abb3134SXin Li 81*2abb3134SXin Li // Raw bits 82*2abb3134SXin Li assert(encoder.EncodeBits(0x123, &out)); // returns false on error 83*2abb3134SXin Li printf("0x123 encoded with RAPPOR: %0x, cohort %d\n", out, encoder.cohort()); 84*2abb3134SXin Li} 85*2abb3134SXin Li``` 86*2abb3134SXin Li 87*2abb3134SXin LiDependencies 88*2abb3134SXin Li------------ 89*2abb3134SXin Li 90*2abb3134SXin Li`rappor::Deps` is a struct-like object that holds the dependencies needed by 91*2abb3134SXin Lithe API. 92*2abb3134SXin Li 93*2abb3134SXin LiThe application must provide the following values: 94*2abb3134SXin Li 95*2abb3134SXin Li- cohort: An integer between 0 and `num_cohorts - 1`. Each value is assigned 96*2abb3134SXin Li with equal probability to a client process. 97*2abb3134SXin Li- client_secret: A persistent client secret (used for deterministic randomness 98*2abb3134SXin Li in the PRR, i.e. "memoization" requirement). 99*2abb3134SXin Li- hash_func - string hash function implementation (e.g. MD5) 100*2abb3134SXin Li- hmac_func - HMAC-SHA256 implementation 101*2abb3134SXin Li- irr_rand - randomness for the IRR 102*2abb3134SXin Li 103*2abb3134SXin LiWe provide an implementation of `hash_func` and `hmac_func` and using OpenSSL. 104*2abb3134SXin LiIf your application already has a different implementation of these functions, 105*2abb3134SXin Liyou can implement the `HashFunc` and HmacFunc` interfaces. 106*2abb3134SXin Li 107*2abb3134SXin LiWe provide two example implementations of `irr_rand`: one based on libc 108*2abb3134SXin Li`rand()` (insecure, for demo only), and one based on Unix `/dev/urandom`. 109*2abb3134SXin Li 110*2abb3134SXin LiError Handling 111*2abb3134SXin Li-------------- 112*2abb3134SXin Li 113*2abb3134SXin LiNote that incorrect usage of the `SimpleEncoder` and `Protobuf` constructors 114*2abb3134SXin Limay cause *runtime assertions* (using `assert()`). For example, if 115*2abb3134SXin LiParams.num\_bits is more than 32, the process will crash. 116*2abb3134SXin Li 117*2abb3134SXin LiEncoders should be initialized at application startup, with constant 118*2abb3134SXin Liparameters, so this type of error should be seen early. 119*2abb3134SXin Li 120*2abb3134SXin LiThe various `Encode()` members do *not* raise assertions. If those are used 121*2abb3134SXin Liincorrectly, then the return value will be `false` to indicate an error. These 122*2abb3134SXin Lifailures should be handled by the application. 123*2abb3134SXin Li 124*2abb3134SXin LiMemory Management 125*2abb3134SXin Li----------------- 126*2abb3134SXin Li 127*2abb3134SXin LiThe `Encoder` instances contain pointers to `Params` and `Deps` instances, but 128*2abb3134SXin Lidon't own them. In the examples, all instances live the stack of `main()`, so 129*2abb3134SXin Liyou don't have to worry about them being destroyed. 130