From fc4413a057fa0e35eabc98c61ffcc97f5f4c6b3c Mon Sep 17 00:00:00 2001 From: Gidon Gershinsky Date: Thu, 4 Aug 2022 09:23:16 +0300 Subject: [PATCH 1/4] initial commit --- format/gcm-stream-spec.md | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 format/gcm-stream-spec.md diff --git a/format/gcm-stream-spec.md b/format/gcm-stream-spec.md new file mode 100644 index 000000000000..f4c9015ad3bf --- /dev/null +++ b/format/gcm-stream-spec.md @@ -0,0 +1,93 @@ +--- +title: "AES GCM Stream Spec" +url: gcm-stream-spec +toc: true +disableSidebar: true +--- + + +# AES GCM Stream (AGS) file format extension + +## Background and Motivation + +Iceberg supports a number of data file formats. Two of these formats (Parquet and ORC) have built-in encryption capabilities, that allow to protect sensitive information in the data files. However, besides the data files, Iceberg tables also have metadata files, that keep sensitive information too (e.g., min/max values in manifest files, or bloom filter bitsets in puffin files). Metadata file formats (AVRO, JSON, Puffin) don't have encryption support. + +Moreover, with the exception of Parquet, no Iceberg data or metadata file format supports integrity verification, required for end-to-end tamper proofing of Iceberg tables. + +This document specifies details of a simple file format extension that adds encryption and tamper-proofing to any existing file format. + +## Goals + +* Metadata encryption: enable encryption of manifests, manifest lists, snapshots and stats. +* Avro data encryption: enable encryption of data files in tables that use the Avro format. +* Tamper proofing of Iceberg data and metadata files. + +## Technical approach + +AGS leverages the Iceberg EncryptionManager interface that converts OutputFile objects (produced by Iceberg Avro and other writers) into EncryptedOutputFile objects. The PositionOutputStream, produced by the AGS EncryptedOutputFile, splits the output bytes into equal-size blocks (plus residue), and encrypts/signs the blocks with a given encryption key. +On the reader side, the Iceberg EncryptionManager converts EncryptedInputFile objects into InputFile objects consumable by Iceberg Avro and other readers. The AGS SeekableInputStream decrypts the stream blocks and verifies their integrity, using the encryption key. +The encryption, decryption and tamper proofing operations are transparent to Iceberg Avro, JSON and Puffin libraries. + +### Encryption algorithm + +AGS uses the standard AEG GCM cipher, and supports all AES key sizes: 128, 192 and 256 bits. + +AES GCM is an authenticated encryption. Besides data confidentiality (encryption), it supports two levels of integrity verification (authentication): of the data (default), and of the data combined with an optional AAD (“additional authenticated data”). An AAD is a free text to be authenticated, together with the data. The structure of AGS AADs is described below. + +AES GCM requires a unique vector to be provided for each encrypted block. In this document, the unique input to GCM encryption is called nonce (“number used once”). AGS encryption uses the RBG-based (random bit generator) nonce construction as defined in the section 8.2.2 of the NIST SP 800-38D document. For each encrypted block, AGS generates a unique nonce with a length of 12 bytes (96 bits). + +## Format specification + +### File structure + +The AGS-encrypted files have the following structure + +``` +Magic BlockLength CipherBlock₁ CipherBlock₂ ... CipherBlockₙ +``` + +where + +- `Magic` is four bytes 0x41, 0x47, 0x53, 0x31 ("AGS1", short for: AES GCM Stream, version 1) +- `BlockLength` is four bytes (little endian) integer keeping the length of the equal-size split blocks before encryption. The length is specified in bytes. +- `CipherBlockᵢ` is the i-th encrypted block in the file, with the structure defined below. + +### Cipher Block structure + +Cipher blocks have the following structure + +| nonce | ciphertext | tag | +|-------|------------|-----| + +where + +- `nonce` is the AES GCM nonce, with a length of 12 bytes. +- `ciphertext` is the encrypted block. Its length is identical to the length of the block before encryption ("plaintext"). The length of all plaintext blocks, except the last, is `BlockLength` bytes. The last block keeps the data residue, with a length <= `BlockLength`. +- `tag` is the AES GCM tag, with a length of 16 bytes. + +AGS encrypts all blocks by the GCM cipher, without padding. The AES GCM cipher must be implemented by a cryptographic provider according to the NIST SP 800-38D specification. In AGS, an input to the GCM cipher is an AES encryption key, a nonce, a plaintext and an AAD (described below). The output is a ciphertext with the length equal to that of plaintext, and a 16-byte authentication tag used to verify the ciphertext and AAD integrity. + +### Additional Authenticated Data + +The AES GCM cipher protects against byte replacement inside a ciphertext - but, without an AAD, it can't prevent replacement of one ciphertext with another (encrypted with the same key). AGS leverages AADs to protect against swapping ciphertext blocks inside a file or between files. AGS can also protect against swapping full files - for example, replacement of a metadata file with an old version. AADs are built to reflects the identity of a file and of the blocks inside the file. + +AGS constructs a block AAD from two components: an AAD prefix - a string provided by Iceberg for the file (the file ID), and an AAD suffix (block sequence number in the file, as an int in a 4-byte little-endian form). The block AAD is a direct concatenation of the prefix and suffix parts. + + + + From 8decf43bb238afa4c06fd78fa44a904212ae111d Mon Sep 17 00:00:00 2001 From: Gidon Gershinsky Date: Thu, 4 Aug 2022 09:30:19 +0300 Subject: [PATCH 2/4] clean up --- format/gcm-stream-spec.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/format/gcm-stream-spec.md b/format/gcm-stream-spec.md index f4c9015ad3bf..9dd60ff5f8bc 100644 --- a/format/gcm-stream-spec.md +++ b/format/gcm-stream-spec.md @@ -84,10 +84,6 @@ AGS encrypts all blocks by the GCM cipher, without padding. The AES GCM cipher m ### Additional Authenticated Data -The AES GCM cipher protects against byte replacement inside a ciphertext - but, without an AAD, it can't prevent replacement of one ciphertext with another (encrypted with the same key). AGS leverages AADs to protect against swapping ciphertext blocks inside a file or between files. AGS can also protect against swapping full files - for example, replacement of a metadata file with an old version. AADs are built to reflects the identity of a file and of the blocks inside the file. - -AGS constructs a block AAD from two components: an AAD prefix - a string provided by Iceberg for the file (the file ID), and an AAD suffix (block sequence number in the file, as an int in a 4-byte little-endian form). The block AAD is a direct concatenation of the prefix and suffix parts. - - - +The AES GCM cipher protects against byte replacement inside a ciphertext block - but, without an AAD, it can't prevent replacement of one ciphertext block with another (encrypted with the same key). AGS leverages AADs to protect against swapping ciphertext blocks inside a file or between files. AGS can also protect against swapping full files - for example, replacement of a metadata file with an old version. AADs are built to reflects the identity of a file and of the blocks inside the file. +AGS constructs a block AAD from two components: an AAD prefix - a string provided by Iceberg for the file (with the file ID), and an AAD suffix - the block sequence number in the file, as an int in a 4-byte little-endian form. The block AAD is a direct concatenation of the prefix and suffix parts. From b0b121ed9403ea224111e829ed43cf73822fbe86 Mon Sep 17 00:00:00 2001 From: Gidon Gershinsky Date: Mon, 8 Aug 2022 08:41:29 +0300 Subject: [PATCH 3/4] rm tech approach section --- format/gcm-stream-spec.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/format/gcm-stream-spec.md b/format/gcm-stream-spec.md index 9dd60ff5f8bc..6f4a0c7a2d51 100644 --- a/format/gcm-stream-spec.md +++ b/format/gcm-stream-spec.md @@ -37,13 +37,11 @@ This document specifies details of a simple file format extension that adds encr * Avro data encryption: enable encryption of data files in tables that use the Avro format. * Tamper proofing of Iceberg data and metadata files. -## Technical approach +## Overview -AGS leverages the Iceberg EncryptionManager interface that converts OutputFile objects (produced by Iceberg Avro and other writers) into EncryptedOutputFile objects. The PositionOutputStream, produced by the AGS EncryptedOutputFile, splits the output bytes into equal-size blocks (plus residue), and encrypts/signs the blocks with a given encryption key. -On the reader side, the Iceberg EncryptionManager converts EncryptedInputFile objects into InputFile objects consumable by Iceberg Avro and other readers. The AGS SeekableInputStream decrypts the stream blocks and verifies their integrity, using the encryption key. -The encryption, decryption and tamper proofing operations are transparent to Iceberg Avro, JSON and Puffin libraries. +The output stream, produced by a metadata or data writer, is split into equal-size blocks (plus residue). Each block is enciphered (encrypted/signed) with a given encryption key, and stored in a file in the AGS format. Upon reading, the stored cipherblocks are verified for integrity; then decrypted and passed to metadata or data readers. -### Encryption algorithm +## Encryption algorithm AGS uses the standard AEG GCM cipher, and supports all AES key sizes: 128, 192 and 256 bits. @@ -65,7 +63,7 @@ where - `Magic` is four bytes 0x41, 0x47, 0x53, 0x31 ("AGS1", short for: AES GCM Stream, version 1) - `BlockLength` is four bytes (little endian) integer keeping the length of the equal-size split blocks before encryption. The length is specified in bytes. -- `CipherBlockᵢ` is the i-th encrypted block in the file, with the structure defined below. +- `CipherBlockᵢ` is the i-th enciphered block in the file, with the structure defined below. ### Cipher Block structure From 87e70888cb5cd20d2e472677f7eb20aca16c20f1 Mon Sep 17 00:00:00 2001 From: Gidon Gershinsky Date: Thu, 10 Nov 2022 13:35:56 +0200 Subject: [PATCH 4/4] address review comments --- format/gcm-stream-spec.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/format/gcm-stream-spec.md b/format/gcm-stream-spec.md index 6f4a0c7a2d51..36e07adabad7 100644 --- a/format/gcm-stream-spec.md +++ b/format/gcm-stream-spec.md @@ -21,7 +21,7 @@ disableSidebar: true - limitations under the License. --> -# AES GCM Stream (AGS) file format extension +# AES GCM Stream file format extension ## Background and Motivation @@ -35,25 +35,26 @@ This document specifies details of a simple file format extension that adds encr * Metadata encryption: enable encryption of manifests, manifest lists, snapshots and stats. * Avro data encryption: enable encryption of data files in tables that use the Avro format. +* Support read splitting: enable seekable decrypting streams that can be used with splittable formats like Avro. * Tamper proofing of Iceberg data and metadata files. ## Overview -The output stream, produced by a metadata or data writer, is split into equal-size blocks (plus residue). Each block is enciphered (encrypted/signed) with a given encryption key, and stored in a file in the AGS format. Upon reading, the stored cipherblocks are verified for integrity; then decrypted and passed to metadata or data readers. +The output stream, produced by a metadata or data writer, is split into equal-size blocks (plus last block that can be shorter). Each block is enciphered (encrypted/signed) with a given encryption key, and stored in a file in the AES GCM Stream format. Upon reading, the stored cipherblocks are verified for integrity; then decrypted and passed to metadata or data readers. ## Encryption algorithm -AGS uses the standard AEG GCM cipher, and supports all AES key sizes: 128, 192 and 256 bits. +AES GCM Stream uses the standard AEG GCM cipher, and supports all AES key sizes: 128, 192 and 256 bits. -AES GCM is an authenticated encryption. Besides data confidentiality (encryption), it supports two levels of integrity verification (authentication): of the data (default), and of the data combined with an optional AAD (“additional authenticated data”). An AAD is a free text to be authenticated, together with the data. The structure of AGS AADs is described below. +AES GCM is an authenticated encryption. Besides data confidentiality (encryption), it supports two levels of integrity verification (authentication): of the data (default), and of the data combined with an optional AAD (“additional authenticated data”). An AAD is a free text to be authenticated, together with the data. The structure of AES GCM Stream AADs is described below. -AES GCM requires a unique vector to be provided for each encrypted block. In this document, the unique input to GCM encryption is called nonce (“number used once”). AGS encryption uses the RBG-based (random bit generator) nonce construction as defined in the section 8.2.2 of the NIST SP 800-38D document. For each encrypted block, AGS generates a unique nonce with a length of 12 bytes (96 bits). +AES GCM requires a unique vector to be provided for each encrypted block. In this document, the unique input to GCM encryption is called nonce (“number used once”). AES GCM Stream encryption uses the RBG-based (random bit generator) nonce construction as defined in the section 8.2.2 of the NIST SP 800-38D document. For each encrypted block, AES GCM Stream generates a unique nonce with a length of 12 bytes (96 bits). ## Format specification ### File structure -The AGS-encrypted files have the following structure +The AES GCM Stream files have the following structure ``` Magic BlockLength CipherBlock₁ CipherBlock₂ ... CipherBlockₙ @@ -75,13 +76,13 @@ Cipher blocks have the following structure where - `nonce` is the AES GCM nonce, with a length of 12 bytes. -- `ciphertext` is the encrypted block. Its length is identical to the length of the block before encryption ("plaintext"). The length of all plaintext blocks, except the last, is `BlockLength` bytes. The last block keeps the data residue, with a length <= `BlockLength`. +- `ciphertext` is the encrypted block. Its length is identical to the length of the block before encryption ("plaintext"). The length of all plaintext blocks, except the last, is `BlockLength` bytes. The last block has a non-zero length <= `BlockLength`. - `tag` is the AES GCM tag, with a length of 16 bytes. -AGS encrypts all blocks by the GCM cipher, without padding. The AES GCM cipher must be implemented by a cryptographic provider according to the NIST SP 800-38D specification. In AGS, an input to the GCM cipher is an AES encryption key, a nonce, a plaintext and an AAD (described below). The output is a ciphertext with the length equal to that of plaintext, and a 16-byte authentication tag used to verify the ciphertext and AAD integrity. +AES GCM Stream encrypts all blocks by the GCM cipher, without padding. The AES GCM cipher must be implemented by a cryptographic provider according to the NIST SP 800-38D specification. In AES GCM Stream, an input to the GCM cipher is an AES encryption key, a nonce, a plaintext and an AAD (described below). The output is a ciphertext with the length equal to that of plaintext, and a 16-byte authentication tag used to verify the ciphertext and AAD integrity. ### Additional Authenticated Data -The AES GCM cipher protects against byte replacement inside a ciphertext block - but, without an AAD, it can't prevent replacement of one ciphertext block with another (encrypted with the same key). AGS leverages AADs to protect against swapping ciphertext blocks inside a file or between files. AGS can also protect against swapping full files - for example, replacement of a metadata file with an old version. AADs are built to reflects the identity of a file and of the blocks inside the file. +The AES GCM cipher protects against byte replacement inside a ciphertext block - but, without an AAD, it can't prevent replacement of one ciphertext block with another (encrypted with the same key). AES GCM Stream leverages AADs to protect against swapping ciphertext blocks inside a file or between files. AES GCM Stream can also protect against swapping full files - for example, replacement of a metadata file with an old version. AADs are built to reflects the identity of a file and of the blocks inside the file. -AGS constructs a block AAD from two components: an AAD prefix - a string provided by Iceberg for the file (with the file ID), and an AAD suffix - the block sequence number in the file, as an int in a 4-byte little-endian form. The block AAD is a direct concatenation of the prefix and suffix parts. +AES GCM Stream constructs a block AAD from two components: an AAD prefix - a string provided by Iceberg for the file (with the file ID), and an AAD suffix - the block sequence number in the file, as an int in a 4-byte little-endian form. The block AAD is a direct concatenation of the prefix and suffix parts.