Skip to main content

Example: Sealing and Protected File

This example demonstrates how to seal and unseal data, as well as work with protected files.

Example: Sealing

  • Seal data with MRENCLAVE
SealHandler sealer(SGX_KEYPOLICY_MRENCLAVE);
uint8_t mac_text[] = {0xAA, 0xBB, 0xCC, 0xDD};
sealer.SetAdditionalMacText(mac_text, sizeof(mac_text));

const char* raw_data = "MACProtectedData";
size_t data_len = strlen(raw_data);
// seal
auto sealed_data = sealer.SealData(reinterpret_cast<const uint8_t*>(raw_data), data_len);
if (!sealed_data.has_value()) return false;

// unseal
auto unsealed_data = sealer.UnsealData(sealed_data->data(), sealed_data->size());
if (!unsealed_data.has_value()) return false;

if (std::string(unsealed_data->decrypted_text.begin(), unsealed_data->decrypted_text.end()) != raw_data) return false;
  • Seal data with MRENCLAVE + MRSIGNER
SealHandler sealer(SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER);
uint8_t mac_text[] = {0xAA, 0xBB, 0xCC, 0xDD};
sealer.SetAdditionalMacText(mac_text, sizeof(mac_text));

const char* raw_data = "MACProtectedData";
size_t data_len = strlen(raw_data);
// seal
auto sealed_data = sealer.SealData(reinterpret_cast<const uint8_t*>(raw_data), data_len);
if (!sealed_data.has_value()) return false;

// unseal
auto unsealed_data = sealer.UnsealData(sealed_data->data(), sealed_data->size());
if (!unsealed_data.has_value()) return false;

if (std::string(unsealed_data->decrypted_text.begin(), unsealed_data->decrypted_text.end()) != raw_data) return false;

Example: Protected File

  • Write a protected file with MRENCLAVE + MRSIGNER
std::string content = "The is a protected text file! File content is sealed by seal key.";
Path file_name=Path("test_file_name");
// The size of data to read/write each time.
// For small files, the recommended size is 4KB;
// For big files, the recommended size is 64KB;
// Don't set SIZE_PER_TIME > 256KB.
constexpr uint32_t SIZE_PER_TIME = 4 * 1024; // 4KB each time
uint16_t key_policy=(SGX_KEYPOLICY_MRSIGNER | SGX_KEYPOLICY_MRENCLAVE);

size_t written_size = 0;
size_t left_size = content.size();
ProtectedFileWriter writer(file_name.String().c_str(), FileMode::CreateNew, key_policy);
while (left_size > 0) {
size_t write_size = (left_size > SIZE_PER_TIME) ? SIZE_PER_TIME : left_size;
writer.Write(content.c_str() + written_size, write_size);
left_size -= write_size;
}
writer.Close();
  • Read a protected file (no need to specify policy, as the file already contains the seal policy)
Path file_name=Path("test_file_name");
// The size of data to read/write each time.
// For small files, the recommended size is 4KB;
// For big files, the recommended size is 64KB;
// Don't set SIZE_PER_TIME > 256KB.
constexpr uint32_t SIZE_PER_TIME = 4 * 1024; // 4KB each time
uint8_t buffer[SIZE_PER_TIME] = {0};

size_t read_size = 0;
std::string test_data;
ProtectedFileReader reader(file_name.String().c_str());
while ((read_size = reader.Read(buffer, SIZE_PER_TIME)) > 0) {
test_data.append((char*)buffer, read_size);
}
reader.Close();
important

Writing in this way will generate two files xxx (data ciphertext) and xxx.pfsmeta (metadata used for decryption), so when you move or copy the protected file, you must also bring its metadata file.