Skip to content

Instantly share code, notes, and snippets.

@jeffro256
Last active December 6, 2024 22:24
Show Gist options
  • Save jeffro256/b54af81983f1e24e2e5329408443154d to your computer and use it in GitHub Desktop.
Save jeffro256/b54af81983f1e24e2e5329408443154d to your computer and use it in GitHub Desktop.
CRIB POET

Carrot Recoverable Indistinguishable Blinded Proof Of Existence before Timestamp

What

CRIBPOET lets you prove you knew about information before some point in time by posting a Carrot transaction from your wallet to the Monero blockchain.

  • Carrot - Uses the Carrot addressing protocol, so any wallet with the new Carrot key hierarchy will have the ability to support this scheme by default
  • Indistinguishable - Uses steganography to look like a regular old 2-out transaction
  • Blinded - The commitment to the information contains a blinding factor that makes it impossible to guess the message from the commitment
  • Recoverable - The blinding factor is recoverable through normal Carrot balance recovery, which means you don't have to keep track of any ephemeral information.
  • Proof of Existence before Timestamp - This scheme leverages assumptions about blockchains to prove information existed before some point in time

Notation

See the Carrot notation section

How

Commit

Given message m:

  1. Sample randomness r = RandBytes(16)
  2. Calculate enote ephemeral pubkey De = Hp2("cribpoet commitment" || m || r)
  3. Create internal selfsend enote E1, setting enote_type = "payment" and anchor = r
  4. Create second internal selfsend enote E2, setting enote_type = "change" and anchor = anchornorm
  5. Post transaction containing De, E1, and E2 to blockchain

Reveal

Given message m, randomness r, and a transaction ID txid:

  1. Lookup the enote ephemeral pubkey De from transaction with txid
  2. Recompute the commitment De' = Hp2("cribpoet commitment" || m || r)
  3. Check that De' ?= De

Recovering r

Given message m:

Perform regular internal balance recovery until De ?= Hp2("cribpoet commitment" || m || anchor'). At that point, you know that r = anchor'.

Why it works

Completeness

Unlike in external enotes, the anchor space is unused in internal Carrot enotes. This fact allows us to insert r encrypted there for free. Internal enotes also do not use De arithmetically, only as nonces in hashes when deriving other enotes components. Therefore, De can taken on any value if all enotes are internal, just so long as they are unique.

Security

The function Hp2 is irreversable (supposedly), which means that finding a "pre-image" to the function is hard. In other words, trying to brute force a message into any already-existing enote epehemeral pubkey is practically impossible.

Privacy

The inclusion of the 128-bit blinding factor r makes it computationally impossible to guess m, even if an adversary knows the commitment De. If r were not included in the hash, then simple messages could be reverse-engineered.

Also, because we use the internal sender-receiver secret instead of an external sender-receiver secret, r remains hidden from quantum adversaries. Therefore, this scheme is perfectly forward secret until both m and r and revealed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment