ejson

repository·main·Indexed 23 days ago

https://github.com/shopify/ejson

A utility for managing collections of secrets within source control using public-key/elliptic-curve cryptography. ejson encrypts string values within JSON files, allowing secrets to be stored safely in git repositories while remaining auditable. It provides a CLI for generating keypairs, encrypting files in place, and decrypting data to stdout.

Tokens
1.5K
Snippets
5
Records
18
Agent score
81%

What's inside ejson

  1. Configure the ejson key directory

    main

    By default, ejson looks for keys in /opt/ejson/keys. You can change this location by setting the EJSON_KEYDIR environment variable or by passing the -keydir option to commands.

    To create the default directory:

    mkdir -p /opt/ejson/keys

    macOS Users: You may need to grant your user permission to write to /opt/ejson:

    sudo chown -R $(whoami) /opt/ejson
  2. Encrypt an ejson file

    main

    To encrypt secrets in a JSON file, use ejson encrypt <filename>.

    This command will:

    1. Encrypt any new plaintext string values in the file.
    2. Leave existing encrypted keys untouched.
    3. Leave any keys with property names prefixed with an underscore (_) untouched.

    Note: This command overwrites the specified file.

    ejson encrypt test.ejson
  3. Generate a keypair with ejson keygen

    main

    Use ejson keygen to create new cryptographic keys.

    • To print keys to stdout: Run ejson keygen. This outputs both the Public Key and Private Key to the terminal. This is useful for manual distribution.
    • To write keys to the keydir: Run ejson keygen -w. This writes the keys to your configured keydir (default /opt/ejson/keys) and prints only the Public Key to stdout.
    ejson keygen
    
    ejson keygen -w
  4. Decrypt an ejson file

    main

    To decrypt an ejson file, use ejson decrypt <filename>.

    Requirements for decryption:

    • You must have a file in your keydir whose name is the 64-byte hex-encoded public key exactly as embedded in the ejson document.
    • The contents of that file must be the corresponding hex-encoded private key.

    Note: Unlike encrypt, ejson decrypt does not overwrite the file; it prints the decrypted JSON to stdout.

    ejson decrypt foo.ejson
  5. Understand the ejson file format

    main

    An ejson file is a standard JSON document with specific rules for encryption:

    1. Public Key Requirement: The top level must contain a key named _public_key containing the 32-byte hex-encoded (64 ASCII characters) public key.
    2. Encryption Target: Any string literal that is not an object key is encrypted by default.
    3. Non-encrypted Types: Numbers, booleans, and null values are not encrypted.
    4. The Underscore Prefix: If a key begins with an underscore (e.g., _database_username), its value will not be encrypted. This is used for metadata or the _public_key itself.
    5. Underscore Propagation: Underscores do not propagate to nested objects. In {"_a": {"b": "c"}}, the value `
  6. Encrypt an EJSON file in place

    main
    Use EncryptFileInPlace(filePath string) to encrypt any unencrypted fields within an existing EJSON file. The function uses the public key embedded in the file to perform the encryption and overwrites the original file on disk, preserving the original file mode.
  7. Encrypt data from a reader

    main
    The Encrypt(in io.Reader, out io.Writer) function reads data from the in reader, extracts the public key embedded in the EJSON document, and performs the encryption operation, writing the result to out. It automatically handles multiline string literal collapsing and uses a json.Walker to traverse the document.
  8. Decrypt an ejson stream

    main

    The Decrypt(in io.Reader, out io.Writer, keydir string, userSuppliedPrivateKey string) function decrypts an EJSON stream.

    It follows this logic to find the private key:

    1. Extracts the public key from the input data.
    2. If userSuppliedPrivateKey is provided (non-empty), it uses that string.
    3. Otherwise, it looks for a file in keydir named after the hex-encoded public key (e.g., keydir/<pubkey_hex>) and reads its contents as the private key.
    4. Decodes the resulting hex string into a 32-byte key.

    The decrypted data is written to out.

  9. Decrypt an EJSON file to a byte slice

    main
    Use DecryptFile(filePath, keydir string, userSuppliedPrivateKey string) ([]byte, error) to read an encrypted EJSON file from disk and return its decrypted contents as a byte slice. It uses the same key discovery logic as Decrypt (searching keydir or using a userSuppliedPrivateKey).
  10. Generate an ejson keypair

    main
    Use GenerateKeypair() to create a new public/private keypair. The function returns both keys as hex-encoded strings, which are suitable for display or storage. If you need the raw byte representation, you can use hex.DecodeString on the returned values.