@zkp2p/reclaim-witness-sdk
Version:
<div> <div> <img src="https://raw.githubusercontent.com/reclaimprotocol/.github/main/assets/banners/Attestor-Core.png" /> </div> </div>
148 lines • 10.3 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.REDACTION_CHAR_CODE = exports.REDACTION_CHAR = void 0;
exports.isRedactionCongruent = isRedactionCongruent;
exports.isFullyRedacted = isFullyRedacted;
exports.getBlocksToReveal = getBlocksToReveal;
exports.redactSlices = redactSlices;
exports.binaryHashToStr = binaryHashToStr;
const wire_1 = require("@bufbuild/protobuf/wire");
const tls_1 = require("@reclaimprotocol/tls");
exports.REDACTION_CHAR = '*';
exports.REDACTION_CHAR_CODE = exports.REDACTION_CHAR.charCodeAt(0);
/**
* Check if a redacted string is congruent with the original string.
* @param redacted the redacted content, redacted content is replaced by '*'
* @param original the original content
*/
function isRedactionCongruent(redacted, original) {
// eslint-disable-next-line unicorn/no-for-loop
for (let i = 0; i < redacted.length; i++) {
const element = redacted[i];
const areSame = element === original[i]
|| (typeof element === 'string' && element === exports.REDACTION_CHAR)
|| (typeof element === 'number' && element === exports.REDACTION_CHAR_CODE);
if (!areSame) {
return false;
}
}
return true;
}
/**
* Is the string fully redacted?
*/
function isFullyRedacted(redacted) {
for (const element of redacted) {
if (element !== exports.REDACTION_CHAR
&& element !== exports.REDACTION_CHAR_CODE) {
return false;
}
}
return true;
}
/**
* Given some plaintext blocks and a redaction function, return the blocks that
* need to be revealed to the other party
*
* Use case: we get the response for a request in several blocks, and want to redact
* pieces that go through multiple blocks. We can use this function to get the
* blocks that need to be revealed to the other party
*
* @example if we received ["secret is 12","345","678. Thanks"]. We'd want
* to redact the "12345678" and reveal the rest. We'd pass in the blocks and
* the redact function will return the redactions, namely [10,19].
* The function will return the blocks ["secret is **","***. Thanks"].
* The middle block is fully redacted, so it's not returned
*
* @param blocks blocks to reveal
* @param redact function that returns the redactions
* @returns blocks to reveal
*/
async function getBlocksToReveal(blocks, redact, performOprf) {
const slicesWithReveal = blocks.map(block => ({
block,
// copy the plaintext to avoid mutating the original
redactedPlaintext: new Uint8Array(block.plaintext)
}));
const total = (0, tls_1.concatenateUint8Arrays)(blocks.map(b => b.plaintext));
const redactions = redact(total);
if (!redactions.length) {
return 'all';
}
let blockIdx = 0;
let cursorInBlock = 0;
let cursor = 0;
for (const redaction of redactions) {
await redactBlocks(redaction);
}
// only reveal blocks that have some data to reveal,
// or are completely plaintext
return slicesWithReveal
.filter(s => !isFullyRedacted(s.redactedPlaintext));
async function redactBlocks(slice) {
while (cursor < slice.fromIndex) {
advance();
}
if (slice.hash) {
const plaintext = total.slice(slice.fromIndex, slice.toIndex);
const { nullifier, responses, mask } = await performOprf(plaintext);
// set the TOPRF claim on the first blocks this
// redaction covers
const toprf = {
nullifier,
responses,
dataLocation: {
fromIndex: cursorInBlock,
length: slice.toIndex - slice.fromIndex
},
mask,
plaintext
};
const block = slicesWithReveal[blockIdx];
block.toprfs || (block.toprfs = []);
block.toprfs.push(toprf);
const nullifierStr = binaryHashToStr(nullifier, toprf.dataLocation.length);
let i = 0;
while (cursor < slice.toIndex) {
slicesWithReveal[blockIdx].redactedPlaintext[cursorInBlock]
= nullifierStr.charCodeAt(i);
advance();
i += 1;
}
}
while (cursor < slice.toIndex) {
slicesWithReveal[blockIdx]
.redactedPlaintext[cursorInBlock] = exports.REDACTION_CHAR_CODE;
advance();
}
}
function advance() {
cursor += 1;
cursorInBlock += 1;
if (cursorInBlock >= blocks[blockIdx].plaintext.length) {
blockIdx += 1;
cursorInBlock = 0;
}
}
}
/**
* Redact the following slices from the total
*/
function redactSlices(total, slices) {
const redacted = new Uint8Array(total);
for (const slice of slices) {
for (let i = slice.fromIndex; i < slice.toIndex; i++) {
redacted[i] = exports.REDACTION_CHAR_CODE;
}
}
return redacted;
}
/**
* Converts the binary hash to an ASCII string of the expected length.
* If the hash is shorter than the expected length, it will be padded with
* '0' characters. If it's longer, it will be truncated.
*/
function binaryHashToStr(hash, expLength) {
return (0, wire_1.base64Encode)(hash).padEnd(expLength, '0').slice(0, expLength);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkYWN0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9yZWRhY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQXVCQSxvREFnQkM7QUFLRCwwQ0FhQztBQW9CRCw4Q0EwRkM7QUFLRCxvQ0FVQztBQU9ELDBDQUVDO0FBL0xELGtEQUFzRDtBQUN0RCw4Q0FBNkQ7QUFHaEQsUUFBQSxjQUFjLEdBQUcsR0FBRyxDQUFBO0FBQ3BCLFFBQUEsbUJBQW1CLEdBQUcsc0JBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFhL0Q7Ozs7R0FJRztBQUNILFNBQWdCLG9CQUFvQixDQUNuQyxRQUFXLEVBQ1gsUUFBVztJQUVYLCtDQUErQztJQUMvQyxLQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUMzQixNQUFNLE9BQU8sR0FBRyxPQUFPLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQztlQUNuQyxDQUFDLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxPQUFPLEtBQUssc0JBQWMsQ0FBQztlQUMzRCxDQUFDLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxPQUFPLEtBQUssMkJBQW1CLENBQUMsQ0FBQTtRQUNwRSxJQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixPQUFPLEtBQUssQ0FBQTtRQUNiLENBQUM7SUFDRixDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUE7QUFDWixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixlQUFlLENBQzlCLFFBQVc7SUFFWCxLQUFJLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQy9CLElBQ0MsT0FBTyxLQUFLLHNCQUFjO2VBQ3ZCLE9BQU8sS0FBSywyQkFBbUIsRUFDakMs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
;