This module implements a cryptographic accumulator, which allows the holder of a private key to prove that a given token is contained within a set without revealing the contents of the set.
Methods are all implemented with both synchronous and asynchronous flavours.
// Import the library
var Acc = require("cryptomancy-accumulator");
// You'll need a source of entropy too
var Source = require("cryptomancy-source");
// You probably want cryptographically secure entropy for key generation...
var secure = Source.bytes.secure(); // a function...
// Finally, you'll most likely want to be able to convert formats
var Format = require("cryptomancy-format");
Generate a set of keys asynchronously.
Acc.genkeys(secure, function (err, keys) {
console.log(keys);
/*
'keys' is an object containing some large numbers,
encoded as Uint8Arrays.
keys include two large random primes P and Q
which ought to be kept secret.
N is the product of those primes.
it acts as a public key.
people will need it to verify your proofs
Totient is derived from P and Q, and is a bit less sensitive
than either, but you should still keep it secret!
*/
});
As above, but synchronous.
var keys = Acc.genkeys(secure);
You shouldn't need to use this function, but it's exposed anyway.
Call it with a Uint8Array and it will return a prime number encoded as a another Uint8Array. Given the same input, it will yield the same prime. This is important, as the verification function depends on its determinacy.
var u8 = Format.decodeUTF8('pewpewpew');
Acc.hashToPrime(u8, function (err, function (err, prime) {
console.log(prime);
});
As above, but synchronous.
var prime = Acc.hashToPrime(Format.decodeUTF8('pewpewpew'));
Create an accumulator and byproducts using your secret key
var items = [
'a',
'list',
'of',
'secret',
'words',
].map(function (item) {
// remember that the accumulator is made from Uint8Arrays
return Format.decodeUTF8(item);
});
Acc.secretly(keys, items, function (err, result) {
console.log(result);
/* result is an object containing:
acc: a Uint8Array representing a very large number
composed of all the prime factors derived from your items.
witnesses: an array of Uint8Arrays, each representing the
aggregation of all but one of the items prime factors.
the prime derived by `item[i]` has `witnesses[i]` as its complement.
primes: you shouldn't need to use the primes, but they're
returned anyway. also in Uint8Array form.
*/
});
As above, but synchronous.
var result = Acc.secretly.sync(keys, items);
You can produce the same output as Acc.secretly
using only the public key if you provide all the same inputs.
Acc.publicly(keys, items, function (err, result) {
console.log(result);
// result should be exactly equivalent to that returned from 'privately'
});
As above, but synchronous.
var result = Acc.publicly.sync(keys, items);
The creator of an accumulator has a set of 'witnesses', which can be used as a proof that a particular prime is encoded within the accumulator.
// as mentioned above, each 'witness' is basically the set-theoretic
// complement of a particular item's prime.
// verification checks that modular multiplication of the witness and item
// produces a value equal to that of the supplied accumulator.
// verification only requires 'N'
// don't go distributing your private keys
Acc.verify(keys, acc, witness, item, function (err, bool) {
if (bool) {
// the supplied witness proves that the supplied item
// is indeed contained within the accumulator
}
// but you can't prove the negative
// this lends the system some interesting properties for deniability
});
As above, but synchronous.
var bool = Acc.verify(keys, acc, witness, item);
if (bool) {
// the witness proves that the item is present in acc
}