Can I Prove To You I Have Added Data … Without Revealing Any Other Data?

While many will see Python as the natural language to turn to in Cybersecurity, Node.js is just as good, and probably provides access to…

Photo by Bernard Hermant on Unsplash

Accumulators, Witnesses and Zero Knowledge Proofs in Node.js

While many will see Python as the natural language to turn to in Cybersecurity, Node.js is just as good, and probably provides access to more library, and is widely compatiable on systems. Perhaps Python and Node.js suffer from a poor usage of syntax, but they are so usual in scripting code.

In this case we will implement an accumulator and allows Bob to add values onto a fixed-length digest, and to provide proof of the values added, without revealing them within the accumulated value. In this case we will use a basic ECC method to make commitments to data elements and use Node.js to implement.

The code in Node.js to add e and which is a hash of a message (msg) onto the secret key of sk is:

acc = acc.multiply(e.add(sk).mod(n))

This takes the current accumulator value (acc) and multiplies by e+sk. The reason that we have methods for the arithmetic operations, is that we are dealing with Big Integers, and which have a much greater scope than our integer data types.

To remove the added value:

z = z.multiply(e.add(sk).mod(n).modInverse(n))

and where n is the order of the curve. This takes the current accumulator value (acc) and divides by e+sk.

The outline code in the following adds to message, and then verifies they have been added. We will then delete the second value, and prove that it does not exist. Finally we will prove that a value does not exist, and that has never existed on the accumulator: [here]

const {Accumulator, Prover} = require('./ecc-acc/index')
const ec = require('ecurve')
const curve = ec.getCurveByName('secp256k1')
const hash = 'sha256'
const accumulator = new Accumulator(curve, hash)
const prover = new Prover(curve, hash)
msg1 = '1'
msg2 = '3'
var args = process.argv;
if (args.length>1) msg1=args[2];
if (args.length>2) msg2=args[3];
witness = accumulator.add(msg1)
rtn=accumulator.verify(witness)
console.log("== Adding data to accumulator ===");
console.log("Adding: ",msg1," Verified:\t",rtn);
prover.update(witness) 

witness = accumulator.add(msg2)
rtn=accumulator.verify(witness)
console.log("== Adding data to accumulator ===");
console.log("Adding: ",msg2," Verified:\t",rtn);
console.log("\nNow deleting ",msg2)
witness = accumulator.del(witness)
console.log("== Deleting data to accumulator ===");
console.log("Deleting: ",msg2," Verified:\t",rtn);
prover.update(witness)
witness = prover.prove(msg2)
rtn=accumulator.verify(witness)
console.log("Does element exist:\t", rtn);

console.log("\nDeleting bob123")
witness = prover.prove('bob123')
rtn=accumulator.verify(witness)
console.log("Does element exist:\t", rtn);

A sample run: [here]

== Adding data to accumulator ===
Adding: Bob Verified: true
== Adding data to accumulator ===
Adding: Alice Verified: true
Now deleting  Alice
== Deleting data to accumulator ===
Deleting: Alice Verified: true
Does element exist: false
Deleting bob123
Does element exist: false

Conclusions

Accumulators are a cool addition to zero-knowledge methods, and allows us to put values into a secret store, and for us to then prove that we have knowledge of values.

If you are interested in Zero-knowledge Proofs (ZKPs), try here:

https://asecuritysite.com/zero/

and for Node.js:

https://asecuritysite.com/javascript