aboutsummaryrefslogtreecommitdiff
path: root/client/cpp/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'client/cpp/README.md')
-rw-r--r--client/cpp/README.md129
1 files changed, 129 insertions, 0 deletions
diff --git a/client/cpp/README.md b/client/cpp/README.md
new file mode 100644
index 0000000..7ac73da
--- /dev/null
+++ b/client/cpp/README.md
@@ -0,0 +1,129 @@
+RAPPOR C++ Client
+=================
+
+We provide both a low level and high level client API. The low level API
+implements just the RAPPOR encoding algorithm on strings, with few
+dependencies.
+
+The high level API provides wrappers that bundle encoded values into Protocol
+Buffer messages.
+
+Build Instructions
+------------------
+
+You'll need a C++ compiler, the protobuf compiler, and a library that
+implements common hash functions (e.g. OpenSSL).
+
+On Ubuntu or Debian, the protobuf compiler and header files can be installed
+with:
+
+ sudo apt-get install protobuf-compiler libprotobuf-dev
+
+OpenSSL can be installed with:
+
+ sudo apt-get install libssl-dev
+
+Test
+----
+
+After installing dependencies, You can test it out easily on your machine:
+
+ ./demo.sh quick-cpp
+
+This builds the test harness using a Makefile, and then runs the regtest.sh
+simulation. The last few lines of output will look like this:
+
+ Done running all test instances
+ Instances succeeded: 1 failed: 0 running: 0 total: 1
+ Wrote _tmp/cpp/results.html
+ URL: file:///usr/local/google/home/andychu/git/rappor/_tmp/cpp/results.html
+
+Open the HTML file to see a plot and stats.
+
+
+Encoder
+-------
+
+The low level API is `Encoder`. You instantiatate it with RAPPOR encoding
+parameters and application dependencies. It has a method `EncodeString()` that
+takes an input string (no other types), sets an output parameter of type
+`rappor::Bits`, and returns success or failure.
+
+```cpp
+#include <cassert>
+
+#include "encoder.h"
+#include "openssl_hash_impl.h"
+#include "unix_kernel_rand_impl.h"
+
+int main(int argc, char** argv) {
+ FILE* fp = fopen("/dev/urandom", "r");
+ rappor::UnixKernelRand irr_rand(fp);
+
+ rappor::Deps deps(rappor::Md5, "client-secret", rappor::HmacSha256,
+ irr_rand);
+ rappor::Params params(32, // num_bits (k)
+ 2, // num_hashes (h)
+ 128, // num_cohorts (m)
+ 0.25, // probability f for PRR
+ 0.75, // probability p for IRR
+ 0.5); // probability q for IRR
+
+ const char* encoder_id = "metric-name";
+ rappor::Encoder encoder(encoder_id, params, deps);
+
+ // Now use it to encode values. The 'out' value can be sent over the
+ // network.
+ rappor::Bits out;
+ assert(encoder.EncodeString("foo", &out)); // returns false on error
+ printf("'foo' encoded with RAPPOR: %0x, cohort %d\n", out, encoder.cohort());
+
+ // Raw bits
+ assert(encoder.EncodeBits(0x123, &out)); // returns false on error
+ printf("0x123 encoded with RAPPOR: %0x, cohort %d\n", out, encoder.cohort());
+}
+```
+
+Dependencies
+------------
+
+`rappor::Deps` is a struct-like object that holds the dependencies needed by
+the API.
+
+The application must provide the following values:
+
+- cohort: An integer between 0 and `num_cohorts - 1`. Each value is assigned
+ with equal probability to a client process.
+- client_secret: A persistent client secret (used for deterministic randomness
+ in the PRR, i.e. "memoization" requirement).
+- hash_func - string hash function implementation (e.g. MD5)
+- hmac_func - HMAC-SHA256 implementation
+- irr_rand - randomness for the IRR
+
+We provide an implementation of `hash_func` and `hmac_func` and using OpenSSL.
+If your application already has a different implementation of these functions,
+you can implement the `HashFunc` and HmacFunc` interfaces.
+
+We provide two example implementations of `irr_rand`: one based on libc
+`rand()` (insecure, for demo only), and one based on Unix `/dev/urandom`.
+
+Error Handling
+--------------
+
+Note that incorrect usage of the `SimpleEncoder` and `Protobuf` constructors
+may cause *runtime assertions* (using `assert()`). For example, if
+Params.num\_bits is more than 32, the process will crash.
+
+Encoders should be initialized at application startup, with constant
+parameters, so this type of error should be seen early.
+
+The various `Encode()` members do *not* raise assertions. If those are used
+incorrectly, then the return value will be `false` to indicate an error. These
+failures should be handled by the application.
+
+Memory Management
+-----------------
+
+The `Encoder` instances contain pointers to `Params` and `Deps` instances, but
+don't own them. In the examples, all instances live the stack of `main()`, so
+you don't have to worry about them being destroyed.