Skip to content

feat: add Key Committing AES-GCM and AES-CBC support#147

Merged
kessplas merged 32 commits into
stagingfrom
kessplas/kc-gcm-cbc
Mar 18, 2026
Merged

feat: add Key Committing AES-GCM and AES-CBC support#147
kessplas merged 32 commits into
stagingfrom
kessplas/kc-gcm-cbc

Conversation

@kessplas

@kessplas kessplas commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Issue #, if available:

Description of changes:

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@kessplas kessplas changed the base branch from main to staging March 5, 2026 00:59
Comment thread src/s3_encryption/__init__.py Outdated
##= specification/s3-encryption/client.md#key-commitment
##% If the configured Encryption Algorithm is incompatible with the key commitment policy, then it MUST throw an exception.
def __attrs_post_init__(self):
if self.algorithm_suite.is_legacy:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Blocking/Question: Isn't this too bold a claim?
attrs_post_init fires for both the encrypt and decrypt path.
But this error should only be thrown on the encrypt path.
For the decrypt path, it needs to do a check for enable_legacy_unathenticated_modes.

Which I recognize may not be implemented yet, but shouldn't we at least put a TODO here to acknowledge that this is incorrect?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

you are correct,
this parameter needs to be encryption_algorithm instead;
this is what Java et al do.

Comment thread src/s3_encryption/key_derivation.py Outdated
Returns:
The pseudorandom key (PRK).
"""
return hmac.new(salt, ikm, "sha512").digest()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Mild Suggestion: Should sha512 be a constant?

Comment thread src/s3_encryption/key_derivation.py
Comment thread src/s3_encryption/key_derivation.py
Comment thread src/s3_encryption/key_derivation.py
Comment thread src/s3_encryption/pipelines.py
Comment thread src/s3_encryption/pipelines.py Outdated
cmm: AbstractCryptoMaterialsManager = field()

def encrypt(self, plaintext, encryption_context=None):
def encrypt(self, plaintext, encryption_context=None, algorithm_suite=None):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: if there is going to be a default algorithm suite, do not bury it here, but put it in init.
It is nice to have defaults all in one place, as compared to scattered across init, materials, and pipeline.

@kessplas kessplas marked this pull request as ready for review March 11, 2026 23:52
##% The S3EC MUST validate the configured Encryption Algorithm against the provided key commitment policy.
##= specification/s3-encryption/client.md#key-commitment
##% If the configured Encryption Algorithm is incompatible with the key commitment policy, then it MUST throw an exception.
def __attrs_post_init__(self):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise: Award winning error experience.

Comment thread src/s3_encryption/pipelines.py Outdated
Comment on lines +54 to +55
if algorithm_suite is None:
algorithm_suite = AlgorithmSuite.ALG_AES_256_GCM_IV12_TAG16_NO_KDF

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Issue: I am still against hiding defaults in pipeline.
Move this to init and make algorithm_suite a required argument.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Also it should be KC GCM as default.

Comment thread src/s3_encryption/pipelines.py
Comment thread src/s3_encryption/pipelines.py
Comment thread src/s3_encryption/pipelines.py Outdated
Comment on lines +198 to +201
commitment_policy: CommitmentPolicy = field(
default=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)
enable_legacy_unauthenticated_modes: bool = field(default=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Question: It appears we are recreating the config object here.
Should we just pass the config object in as a required parameter?
i.e: the config object is a field of the pipeline?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Maybe? I think it could go either way. So I'm inclined to leave it as is.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

As you know, I am generally against burying or having duplicate definitions of a default.
commitment_policy and enable_legacy_unauthenticated_modes should be required arguments here, to ensure that they are always plumbed through.

Comment thread src/s3_encryption/pipelines.py
Comment thread src/s3_encryption/pipelines.py
Comment thread test/test_key_derivation.py Outdated
@kessplas kessplas changed the title Kessplas/kc gcm cbc feat: add Key Committing AES-GCM and AES-CBC support Mar 13, 2026

@texastony texastony left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I really do not like duplicate definitions of a default.
That seems like an anti-pattern.
How opposed is @kessplas to making Algorithm Suite a required argument to encryption materials and the pipeline methods, and only an optional argument to the config?

Comment thread src/s3_encryption/materials/materials.py
Comment on lines +40 to +45
encryption_algorithm: AlgorithmSuite = field(
default=AlgorithmSuite.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY
)
commitment_policy: CommitmentPolicy = field(
default=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Are there no Duvet annotations for these defaults?
You would think there would be.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You would. Cut #155 to update spec.

Comment thread src/s3_encryption/pipelines.py
Comment thread src/s3_encryption/pipelines.py Outdated
Comment on lines +198 to +201
commitment_policy: CommitmentPolicy = field(
default=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)
enable_legacy_unauthenticated_modes: bool = field(default=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

As you know, I am generally against burying or having duplicate definitions of a default.
commitment_policy and enable_legacy_unauthenticated_modes should be required arguments here, to ensure that they are always plumbed through.

Comment thread src/s3_encryption/pipelines.py
Comment thread test/test_default_algorithm_commitment.py
Comment thread test/test_encryption.py Outdated
Comment thread test/test_encryption.py
Comment thread test/test_encryption.py
@kessplas kessplas merged commit 268bd4b into staging Mar 18, 2026
5 checks passed
@kessplas kessplas deleted the kessplas/kc-gcm-cbc branch March 18, 2026 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants