# Sealed Predictions - A Solution.

Hi - I'm George, and have been a long time silent follower of LessWrong and other reasoning/rationality forums. I work in AI - for personal reasons I'd like to remain pseudo-anonymous for the time being. This is my first post on LessWrong. This post is the result of me observing a problem that relates to the prediction community, and trying to address it. 

> I would like to make a prediction, but I'm not ready to raise the subject of the prediction just yet. So to show that it was not just obvious in hindsight, and to strengthen my precommitment to write an article about it later, here is the sha1sum of my prediction: 9805a0c7bf3690db25e5753e128085c4191f0114.

[*A Sealed Prediction*](https://www.lesswrong.com/posts/eiif58ahyvxdsNvPR/a-sealed-prediction)*,* [***Quirinus_Quirrell***](/users/quirinus_quirrell?from=post_header)*, lesswrong.com, 28th Jan 2011.*

The Problem
-----------

Being able to say 'I predicted this' confers some capital (money, kudos) to the predictor. However it also typically means publishing your prediction, which holds a degree of informational hazard - publishing leaks information, which could inform or alter the prediction itself.

This is a [problem](https://www.lesswrong.com/posts/DHKaRB2dKYHYNrBGj/is-there-a-convenient-way-to-make-sealed-predictions) [raised](https://www.lesswrong.com/posts/2uroahLGmryqjizzE/sealed-predictions-thread) [regularly](https://www.lesswrong.com/posts/eiif58ahyvxdsNvPR/a-sealed-prediction) by this community, and a solution has been suggested in the form of publishing hashes of your predictions until an 'unsealing' date. I don't think this is sufficient, from a practical or security standpoint - it is not scalable, structured, or secure. I thought I could address this problem, and have attempted to do so.

The Solution
------------

I have built a web app. As this is my first post here, I am (slightly) mortified that even stating this will come across as too self promotional. However I think this is a useful enough thing to exist in the world, and believe that the LessWrong community could benefit from it. So, to properly align incentives here, I want to be clear up front - the app is free to use, and has no ads or trackers.

The premise is simple - a user should be able to make a claim, create an immutable hash of the claim text, seal it, and set a date for unsealing. Once sealed, a user should not be able to edit or delete the claim. The claim should unseal itself on the date given, and on unsealing some check should be performed to ensure that the claim has maintained its integrity. 

Cryptographic Implementation
----------------------------

I have implemented this as follows. 

A user authors a claim. There are three fields - Premise, Claim, and Reveal Date. Premise is a publicly visible teaser about the claim. Claim is the claim itself. Reveal date is the date on which the claim will automatically be revealed.

When the user clicks submit, the claim is first sent to a content moderation service ([OAI's Omni Moderation](https://developers.openai.com/api/docs/guides/moderation/)). This felt like an important thing to implement to prevent the sorts of claims which could be harmful. If offensive content is flagged, the claim is rejected at this point, and the user is informed why.

The claim is first encrypted via an AES-256-GCM data encryption key (DEK), created via Amazon Web Services Key Management System (AWS KMS). Then, the DEK is encrypted by a master key which also sits within AWS KMS. Both the encrypted DEK and the encrypted claim are stored in a Postgres database. The encryption algorithm uses a random initialisation vector (IV) so that identical plaintext produce different cipher texts. An auth tag is generated as a byproduct of the encryption, which acts as a checksum to detect tampering and guarantee integrity. 

For each claim, the following is stored:

*   Claim cipher text
*   IV
*   Auth tag
*   Encrypted DEK
*   Master key ID (to set which master key was used for the encryption)

Separate from the encryption, a hash and an n_once [^rlvk13ff41c] are also generated. The n_once prevents rainbow table attacks[^cwwt7jfsokt] \- without it, anyone could hash common prediction plaintext in an attempt to match them against the hash. The hash is formed as: 

    SHA-256("sealed:{n_once}:{claim_text}")

After sealing, anybody can see the hash and the premise, but the text is locked away until reveal date and time.

When the reveal date and time arrives, the following happens:

*   The claim is fetched from the database
*   A request is sent to the KMS to decrypt the encrypted DEK.
*   The plaintext DEK plus the IV plus the auth tag are used to decrypt the claim ciphertext
*   The hash is verified - the claim text is hashed again per the above, and the output is compared to the initial hash to ensure integrity. 
*   The plaintext claim is published
*   The n\_once is also published so that anyone can check the hash + n\_once matches the claim

Design Choices
--------------

There were decisions made in the design which have some notable consequences. 

*   Users cannot delete claims. This is to prevent claim spamming - making many similar claims and then deleting those which were not accurate. This may feel somewhat uncomfortable to some users, but I suggest this is the best approach for now. Other options include allowing users to delete claims within a time window, or noting publicly the date and premise of claims that have been deleted. Practical usage of the app will uncover which is the best path here.
*   Users can see (but not edit) their sealed claims. This is to allow users to remind themselves which claims they have made. It seems there is little or no marginal security risk in this - if a user wanted to share their claim publicly before the reveal for some reason, they could do this anyway. 
*   Claims are not end to end encrypted. The server sees the plaintext claim prior to encryption (but does not store it), and so does the content moderating system. This addresses various practical liability issues, and one major implementation issue - if the user is required to hold a private key to unlock the claim, it becomes very difficult to orchestrate the decryption process, requiring storage local to the user and a more complex app development. 
*   It is possible for someone with access to the database, and to the web server's environmental variables, to decrypt claims ahead of their release date. Currently this access is limited just one individual - me. But the result is that there is *some* trust assumed in the system. However, this requires active meddling in the database - fetching the DEK, decrypting it, etc[^219qjmy0zfv]. There is an active area of cryptographic research called timed-release encryption which would mitigate this - it is not mature enough to implement today, but an area I keep a keen eye on.
*   I decided not to implement any blockchain for this project, due to complexity, optics, and user experience.[^j8nclkk6cn]
*   Users can vote on revealed claims (and can star sealed ones, to be notified on their revealing). The hope is that high quality predictions are upvoted more, which can then be combined into a 'score' for a user relating to their track record.
*   I decided to implement AI fact checking on the claims. Three AI models (ideally those at the very frontier, but currently the less expensive ones for beta testing[^84ja6rlls45]) each return a verdict — supported, contradicted, partially supported, insufficient evidence, or not yet verifiable — and these are combined into a consensus score. This displays a label next to the claim. I have a suspicion this may be a controversial feature and am entirely open to abandoning it. The AI models do not affect the scoring mechanic mentioned above.

What next?
----------

This app is designed to serve the communities that would find it most useful. To help with this, **I am looking for beta testers.** If you are interested in sealing some claims, checking for bugs, interacting with other claims, and generally supporting the project, please reach out and I can share invite codes. 

The project is not entirely free to run. For transparency, I do have a link on the website to 'BuyMeACoffee' for donations. These will be used solely for keeping the servers running. 

If this is popular, I will continue running it[^qcgea87xg9]. If it doesn't catch on, I plan to lock it down to new users, whilst honouring claims which have already been sealed until their release dates.

The website is here: [https://sealed-app.com](https://sealed-app.com) 

[^rlvk13ff41c]: A n_once is a random number that is used just once in a cryptographic algorithm. 

[^cwwt7jfsokt]: A rainbow table is a precomputed table for caching the outputs of a cryptographic hash function.  

[^219qjmy0zfv]: This process will also leave traces in the deployment, database, and KMS logs. I am considering how I could make each DEK one use only to mitigate this - it wouldn't prevent early decryption from a rogue admin but would make it apparent. 

[^j8nclkk6cn]: It would be slower, risks this appearing as a 'crypto app', and would increase computational overhead and cost. 

[^84ja6rlls45]: Currently from OAI, Anthropic, and Google 

[^qcgea87xg9]: Which will mean upgrading from the free tiers for numerous service providers