This is the repo of cipher, an artwork by Paul Seidler. If you are interested in experimenting with ZK-encrypted data on-chain, head over to the
Geheimnis Repository, which is a better starting point because it generates clean circuits and contracts.
Cipher is already opinionated toward encrypting and verifying specific Turmite data, so use this repo only if you are interested in understanding Cipher — otherwise head over to Geheimnis Repository.
The main part of cipher is an ERC-721 extension that stores encrypted metadata on-chain and enforces zero-knowledge proof-verified re-encryption on every transfer.
Token metadata is encrypted using Poseidon symmetric encryption, keyed via ECDH on the Baby Jubjub curve. Standard transferFrom is replaced by verifiedTransferFrom, which requires a Groth16 proof that the sender correctly decrypted the old ciphertext and re-encrypted it for the new owner — without revealing the plaintext on-chain. An additional reCipher operation lets the owner re-encrypt their data under a new keypair at any time.
See EIP-XXXX.md for the full technical specification.
| Contract | Address |
|---|---|
EncryptedERC721 |
0x0fbc8f60cdfc6412f7068c3d71041e2c1f78ed7d |
CipherMinter |
0xff158f4b0b1d71b6d666747df79c47325fcf29b4 |
Groth16Verifier (transfer) |
0xe8fad310055f8607e3afd15c05d8b1c794e78afd |
Groth16Verifier (recipher) |
0x0820baedf4418a84f66ede6b555eca2ff3327cbe |
renderMetadata |
0x7963f1a78c989e0c55732a3ab20aaabd3b17a5cc |
NFTMarketplace |
0x25f77d92b771cfa7ddf5944bbc0c4e688e2f4ee7 |
cipher/
├── circuits/ ZK circuits and proof generation scripts
│ ├── circuits/ Circom source files
│ ├── scripts/ Circuit build scripts (compile + trusted setup)
│ └── calldata/ Pre-generated proof calldata examples
└── contracts/
├── src/ Solidity contracts
├── script/ Foundry deploy scripts
└── test/ Foundry tests
make installmake build # build circuits then contracts
make build-circuits # circuits only
make build-contracts # contracts only (forge build)Circuit compilation downloads a Powers of Tau file and runs the Groth16 trusted setup — this takes several minutes the first time.
make testRuns a full simulation of the mint → transfer → recipher flow and writes proof artifacts to circuits/build/:
make generate-proofsConfig
circomkit.json— circomkit include pathscircuits.json— declares the two circuits with their template names and public signal listspackage.json— npm dependencies and build scripts
Circuit source (circuits/circuits/)
ecdh.circom— ECDH shared key derivation on Baby Jubjub. Takes a private key + public key, outputs the shared secret pointposeidon-cipher.circom— Poseidon symmetric encryption/decryption over BN254, operating on blocks of 3 field elementsposeidon-constants-old.circom— Poseidon MDS matrix and round constants, used byposeidon-cipher.circomecdh-poseidon-cipher.circom— main circuit logic combining ECDH + Poseidon. Contains the deployed templates:EcdhPoseidonCipherKeyDerivationTransfer(transfer) andEcdhPoseidonEncrypt/Decrypt(used by add-new-data)verification-encoded-data.circom— validates the encoded Turmite slot data and wraps the ECDH+Poseidon operations for mint/recipher. ContainsAddNewDataEncryptWithOptionalCheckwhich enforces an optional "only one slot value changed" constraint
Entry points (circuits/circuits/main/)
ecdh-poseidon-key-derivation-cipher-transfer.circom— entry point for the transfer verifieradd-new-data-encrypt-with-check.circom— entry point for the mint/recipher verifier
Build scripts (circuits/scripts/)
buildEcdhPoseidonKeyDerivation.js— compiles the transfer circuit, runs Groth16 trusted setup, generates a proof with test inputsbuildAddNewDataEncryptWithCheck.js— same for the mint/recipher circuit
JS utilities
cryptoUtils.js— key generation, ECDH shared key derivation, JSON file readingencodingUtils.js— encode/decode the three 256-bit slot values storing Turmite state (positions, rulesets, color, parameters) as packed hex stringsgenerateProofData.js— end-to-end simulation of mint → transfer → recipher → transfer-without-recipher, generating all four proof artifacts