Don't use random IVs for AES-GCM for SSE-C #848

Open
opened 2024-08-07 02:42:58 +00:00 by lx · 3 comments
Owner
From this comment : https://news.ycombinator.com/item?id=41173644
quentin added the
action
more-info-needed
scope
security
labels 2024-08-07 09:20:39 +00:00
quentin added the
kind
wrong-behavior
label 2024-08-07 09:36:10 +00:00

To start the discussion:
What about deriving an object encryption key from the provided SSE-C key?
Because the SSE-C key is already a PRK (assumed it was properly generated), HKDF-Expand should be enough:

info = bucket_id + object_name + version_uuid + "garage-object-encryption-key"
oek = hmac_sha256(ssec_key, info)

The OEK could then be used to encrypt the resulting blocks of the object using AES256-GCM and randomly generated 12byte IVs.

To start the discussion: What about deriving an object encryption key from the provided SSE-C key? Because the SSE-C key is already a PRK (assumed it was properly generated), HKDF-Expand should be enough: ``` info = bucket_id + object_name + version_uuid + "garage-object-encryption-key" oek = hmac_sha256(ssec_key, info) ``` The OEK could then be used to encrypt the resulting blocks of the object using AES256-GCM and randomly generated 12byte IVs.
Author
Owner

This looks like a good idea, we just need to find a way to ensure backwards-compatibility with data that is already encrypted in current Garage clusters. Maybe we just need to try decryption with the OEK and if that fails try the original SSE-C key instead?

Also, could you explain what the acronym PRK means?

This looks like a good idea, we just need to find a way to ensure backwards-compatibility with data that is already encrypted in current Garage clusters. Maybe we just need to try decryption with the OEK and if that fails try the original SSE-C key instead? Also, could you explain what the acronym PRK means?

PRK means "pseudorandom key". If the SSE-C Key is generated by using a cryptographically strong Random Number Generator (e,g., using /dev/random), the resulting key can be considered as a PRK.

I am thinking about introducing a kind of plaintext header to encrypted data so that the used encryption scheme can be extracted from the encrypted data itself. This is useful if we need to make again changes in future in the way we encrypt/decrypt objects (e.g. using a different algorithm). Maybe for the beginning, a kind of Garage Object Encryption Scheme version information (uint16) header is already sufficient? Having the Garage Object Encryption Scheme version, additional headers could be easily added in future if needed.

The only open question is, how we could differentiate between encrypted objects with and without such a header prepended. Maybe this can be extracted from the size information of an object? We know that the current encryption scheme will generate 12byte IV and 16byte Authentication Tag of additional bytes to the ciphertext size compared to the plaintext size of the object. If the object is at least 2 bytes bigger in overhead, we would know that there is a header in place. Do we know the ciphertext size and plaintext size of an object in advance to calculate the encryption overhead?

If there is no better way differentiating encrypted objects with and without a header, i think the only way would be as you proposed: Try to parse the header and decrypt according to the included Garage Object Encryption Scheme version information, if this fails, try the old scheme.

PRK means "pseudorandom key". If the SSE-C Key is generated by using a cryptographically strong Random Number Generator (e,g., using /dev/random), the resulting key can be considered as a PRK. I am thinking about introducing a kind of plaintext header to encrypted data so that the used encryption scheme can be extracted from the encrypted data itself. This is useful if we need to make again changes in future in the way we encrypt/decrypt objects (e.g. using a different algorithm). Maybe for the beginning, a kind of Garage Object Encryption Scheme version information (uint16) header is already sufficient? Having the Garage Object Encryption Scheme version, additional headers could be easily added in future if needed. The only open question is, how we could differentiate between encrypted objects with and without such a header prepended. Maybe this can be extracted from the size information of an object? We know that the current encryption scheme will generate 12byte IV and 16byte Authentication Tag of additional bytes to the ciphertext size compared to the plaintext size of the object. If the object is at least 2 bytes bigger in overhead, we would know that there is a header in place. Do we know the ciphertext size and plaintext size of an object in advance to calculate the encryption overhead? If there is no better way differentiating encrypted objects with and without a header, i think the only way would be as you proposed: Try to parse the header and decrypt according to the included Garage Object Encryption Scheme version information, if this fails, try the old scheme.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Deuxfleurs/garage#848
No description provided.