## How Can We Help?

# RSA accumulators

The RSA accumulator must be set up by a trusted operator that randomly chooses two strong 1024 bit RSA primes *p, q*, and publishes the integer *N* = *pq*. The values of *p *and *q* are kept secret. The operator discards the values *p *and *q *after publishing *N*.

*Secure MPC: *The integer *N* can be generated through a *secure multi-party computation *among several independent parties. Unless all the participating parties collude to corrupt the system, then nobody will learn the secret values *p *and *q*. Only a single participating party has to be trusted for the process to work. For Findora deployments, the integer *N* will be generated through a secure MPC among several parties including the initial validator set.

*Initialization:* Set *A* = 3. This value of *A* is the accumulator state head.

*Insertion: *Insertion of a new value *val* into the accumulator uses a function *HashPrime* that hashes arbitrary data to prime integers in the range [0, 2^256). The accumulator state head *A* is updated to the new integer *A := A^**HashPrime(val) **mod N*. The first step of *HashPrime* outputs *hashval* = *SHA256*(*val)*. Then, starting with a counter *nonce = *0, it computes *SHA256*(*nonce, hashval*) and checks if this is prime. If it is not prime then it increments *nonce *and repeats the process until the first value of *nonce* that outputs a prime. The parallel implementation of *HashPrime* tests a range of consecutive *nonce* values in parallel. If more than one output is prime then it selects the lowest, otherwise, it shifts to the next consecutive range.

*Membership witness*: The membership witness for a value *val* inside an accumulator with current state head *A* is the value *A**^(1/x)* mod* N* with *x = HashPrime(val)*. This is an integer value *w* such that *w^**x** = A *mod* N. *The state head of the accumulator just before *val* is inserted is the initial membership witness for *val*. Membership witnesses are updated as the state head changes every time a new value is inserted into the accumulator. When a new value *val** is inserted into the accumulator the current membership witness *w *is updated to *w* := *w^**y* with *y = HashPrime(val*)*.

*Non-membership witness: * If the value *val* is not in the accumulator with current state head *A = 3^**y* *mod N*, then *x* = *HashPrime*(*val*) is co-prime with *Y*. The Euclidean algorithm is used to find a large integer *a* (proportional to *y*) and a smaller integer *b* (proportional to *x*) such that *ax *+ *by* = 1. The non-membership witness for val is (D, b) where D=3^a. The non-membership witness is verified by checking that D^xA^b = 3.

*Deletion: * *Deletion of a value val with x = HashPrime(val) from the accumulator requires computing a value A1/x mod N *(the same as a membership witness for val in A) and updating the state head to A := A^(1/x) mod N. This can be computed in linear time w.r.t to the size of the set if all the values that have been inserted into the accumulator are known. If a membership witness *w* for *val *in A is already known, then deleting *val* is simple: set *A* := *w*.

Membership witnesses for all other values also need to be updated when a value is deleted. If the current state head is A and a value val is removed resulting in the new state head A1 = A^(1/x), then the membership witness w* = A^(1/y) for a value val* with y = HashPrime(val*) is updated to w* := w*^(1/y). Note that w*^(1/y) = A^(1/(xy)).

The efficient algorithm to compute the new membership witness A^(1/(xy)) from the old membership witness w* = A^(1/y) and new state head A1 = A^(1/x) first uses the Euclidean algorithm to find integers a, b satisfying an equation ax + by = 1, and then outputs the integer (A1)^b(w*)^a mod N. This output is a value A^(1/(xy)) because [(A1)b(w*)^a]^xy = [(A^(b/x)A^(a/y)]^(xy) = A^(by + ax) = A.