Skip to main content

File Block Encryption

Overview​

This page describes the file block encryption example, which shows how to use SST session keys to encrypt and decrypt large data sets in fixed-size blocks — without a network connection between entities.

Source: examples/file_block_encrypt_example/ in iotauth/sst-c-api.

What this demonstrates​

  • A writer requests multiple session keys from Auth, generates random key-value pairs, packs them into 32 KB blocks, encrypts each file with a distinct session key shared by its ten blocks, and writes the encrypted blocks to files.
  • A reader loads the writer's metadata, requests the exact session keys needed (by ID) from Auth, reads the encrypted files, decrypts each block, and verifies the result against the original plaintext.

This pattern is applicable to any scenario where data must be encrypted at write time and decrypted later — databases, log archives, sensor recordings, and similar offline use cases.

Key constants​

ConstantValueMeaning
MAX_PLAINTEXT_BLOCK_SIZE32768 (32 KB)Maximum bytes per encrypted block.
TOTAL_BLOCK_NUM10Number of blocks per output file.
TOTAL_FILE_NUM3Number of output files.
MIN_KEY_VALUE_SIZE56Minimum size of a single key-value entry.
MAX_KEY_VALUE_SIZE144Maximum size of a single key-value entry.

Prerequisites​

Build​

cd entity/c/examples/file_block_encrypt_example
mkdir -p build && cd build
cmake ../
make

This produces:

  • block_writer — encrypts and writes blocks
  • block_reader — decrypts and verifies blocks
  • block_reader_load_s_key_list — reader variant that loads keys from a previously saved key list file

Run​

1. Start Auth​

cd auth/auth-server # inside iotauth/iotauth
java -jar target/auth-server-jar-with-dependencies.jar -p ../properties/exampleAuth101.properties

2. Run the writer​

cd entity/c/examples/file_block_encrypt_example/build
./block_writer ../block_writer.config

The writer:

  1. Requests N session keys from Auth (controlled by entityInfo.number_key in the config).
  2. Generates random key-value pairs and packs them into 32 KB blocks.
  3. Zero-pads the unused space when the next entry does not fit in a block.
  4. Encrypts all ten blocks in a file with that file's session key.
  5. Writes encrypted blocks to files and plaintext blocks for later comparison.
  6. Saves block metadata (key IDs, file positions, block lengths) to binary metadata files.

3. Run the reader​

cd entity/c/examples/file_block_encrypt_example/build
./block_reader ../block_reader.config

The reader:

  1. Loads block metadata saved by the writer.
  2. For each file, requests its session key by ID from Auth and uses it for the file's blocks.
  3. Reads and decrypts the encrypted block.
  4. Compares the decrypted output against the saved plaintext to verify correctness.

To test key persistence, run the reader variant that loads keys from disk:

./block_reader_load_s_key_list

This reloads session keys that were saved to disk by the writer instead of re-requesting them from Auth.

Implementation walkthrough​

Writer flow​

// Request N session keys
SST_ctx_t* ctx = init_SST(config_path);
session_key_list_t* keys = get_session_key(ctx, NULL);

// Save key list for the reader to load later (optional)
save_session_key_list(keys, "s_key_list.bin");

// For each block in file i:
// - Fill a 32 KB buffer with random key-value pairs
// - Encrypt with keys->s_key[i]
// - Write encrypted block to file
encrypt_buf_with_session_key(&keys->s_key[i], plaintext, block_len,
&encrypted, &enc_len);
fwrite(encrypted, 1, enc_len, out_file);
free(encrypted);

// Save metadata: key ID, file offset, block length

Reader flow​

// Load metadata from writer
// For each file: look up its session key by ID from Auth
session_key_t* key = get_session_key_by_ID(key_id, ctx, key_list);

// Decrypt the block
decrypt_buf_with_session_key(key, ciphertext, enc_len,
&plaintext, &plain_len);

// Compare with saved plaintext to verify

Key persistence variant​

The writer saves its session key list with:

save_session_key_list(keys, "s_key_list.bin");

The block_reader_load_s_key_list variant uses:

session_key_list_t* loaded = init_empty_session_key_list();
load_session_key_list(loaded, "s_key_list.bin");

This avoids contacting Auth again and is useful for offline decryption scenarios. Password-protected persistence is available via save_session_key_list_with_password / load_session_key_list_with_password.

Config files​

FilePurpose
block_writer.configWriter entity config: Auth coordinates, entity credentials, number of keys.
block_reader.configReader entity config: Auth coordinates, entity credentials.

C++ standalone block example​

The C++ example uses sst::Crypto with a locally generated AES-128-CBC key and 1 KiB input blocks. It does not contact Auth or use the C example's config and metadata files. The key is saved as raw bytes in the requested key file; each encrypted record contains an IV, a ciphertext length, and ciphertext.

From the main repository, with the C++ prerequisites installed:

cd entity/c/cpp/examples/file_block_encrypt_example
cmake -S . -B build
cmake --build build
./build/block_writer input.txt encrypted.bin key.bin
./build/block_reader encrypted.bin key.bin recovered.txt input.txt

Create input.txt first. Passing it as the reader's fourth argument checks recovered blocks against the original.

Next steps​

  • See C API Reference for full function documentation including encrypt_buf_with_session_key and save_session_key_list.
  • See Server/Client Example for a socket-based secure communication example.
  • See IPFS File Sharing for file encryption combined with IPFS storage and Auth-managed key distribution.