Skip to content

Conversation

@ggershinsky
Copy link
Contributor

@ggershinsky ggershinsky commented Oct 22, 2025

Iceberg table encryption has a "key encryption key" that encrypts manifest list key metadata for every snapshot (manifest list) produced in a table. The NIST SP 800-57 document recommends setting a limit of 2 years on the crypto-period of key wrapping (encryption) keys.
However, recording the creation timestamp of key encryption keys in the metadata.json file is not safe in non-REST catalogs, as an attacker can modify this file and update the timestamp to a newer value - making the writers re-use a key encryption key beyond the recommended limit, potentially allowing the attacker to reconstruct the key.
That's why the current code has only one key encryption key (without a timestamp), and requires the users to rotate the key manually every two years for each table. Also, the key metadata of the existing manifest lists has to be re-wrapped (re-encrypted) with the rotated key. Iceberg will need to build such re-wrapping procedure and provide it within two years.

Fortunately, there is a cryptographic solution that doesn't require manual key rotation and metadata re-wrapping. We can use the key encryption key timestamp as an AES GCM signature (AAD) when wrapping the manifest list key metadata. This way, the malicious tampering with timestamps will be detected by Iceberg readers upon decrypting the manifest list key metadata. This solution also enables automatic rotation of the key encryption keys, so the users don't need to run manual re-wrapping procedures on their tables.

This PR implements such auto-rotation solution.

@github-actions github-actions bot added the core label Oct 22, 2025
@huaxingao
Copy link
Contributor

Thanks @ggershinsky for the PR! Is it possible to add a rotation test: insert a KEK with a timestamp older than 2 years and verify a new KEK is created and used?

@ggershinsky
Copy link
Contributor Author

Thanks @ggershinsky for the PR! Is it possible to add a rotation test: insert a KEK with a timestamp older than 2 years and verify a new KEK is created and used?

Sure


sem.setTestTimeShift(TimeUnit.DAYS.toMillis(800));
// above rotation time, key must be different
assertThat(sem.keyEncryptionKeyID()).isNotEqualTo(initialKekID);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Do we want to check that the manifest‑list key metadata is encrypted by the rotated KEK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, can be done.

@ggershinsky ggershinsky reopened this Oct 27, 2025
@huaxingao
Copy link
Contributor

LGTM. Thanks @ggershinsky ! I’ll leave this PR open for a couple more days in case others want to review.

@huaxingao huaxingao merged commit d1a518f into apache:main Oct 29, 2025
83 of 84 checks passed
@huaxingao
Copy link
Contributor

Thanks @ggershinsky for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants