Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/server/compression_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ using namespace dbps::enum_utils;

namespace dbps::compression {

// TODO(Issue #188): Add support for other compressions.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if this is something we want to tackle as part of the project, keep the TODO. if it's a future extension, I recommend removing the todo.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

std::vector<uint8_t> Compress(const std::vector<uint8_t>& bytes, CompressionCodec::type compression) {
if (compression == CompressionCodec::UNCOMPRESSED) {
return bytes;
Expand Down
35 changes: 30 additions & 5 deletions src/server/encryption_sequencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,24 +140,49 @@ bool DataBatchEncryptionSequencer::ConvertAndEncrypt(const std::vector<uint8_t>&
// Compress the joined encrypted bytes
encrypted_result_ = Compress(joined_encrypted_bytes, encrypted_compression_);

} catch (const DBPSUnsupportedException& e) {
// If any stage is as of yet unsupported, default to whole payload (per-block) encryption
// (as opposed to per-value)
}
// If the sequence was interrupted by a DBPSUnsupportedException, allow fallback to per-block encryption
// but only for explicitly unsupported conditions.
// Any conditions that are already supported should not fallback. In those cases, the exception is re-thrown.
catch (const DBPSUnsupportedException& e) {
Comment thread
argmarco-tkd marked this conversation as resolved.

// Compression: Only UNCOMPRESSED and SNAPPY are supported
// TODO(Issue #188): Add support for other compressions.
const bool is_compression_supported = (compression_ == CompressionCodec::UNCOMPRESSED ||
compression_ == CompressionCodec::SNAPPY);

// Format: Only PLAIN is supported
// TODO(Issue #187): Add support for other encodings.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

similar to above - let's keep the TODO only if it's work we plan to complete in the project. Else, let's move these as notes for the future.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

const bool is_format_supported = (format_ == Format::PLAIN);

// Page type: All are supported (DATA_PAGE_V1, DATA_PAGE_V2, DICTIONARY_PAGE)
const bool is_page_supported = true;

// Datatype: All datatypes are supported.
const bool is_datatype_supported = true;

if (is_compression_supported && is_format_supported && is_page_supported && is_datatype_supported) {
// All conditions are supported, therefore an DBPSUnsupportedException exception should not have happened.
// Re-throw the exception.
throw;
}

// Fallback: Use per-block encryption for unsupported combinations.
encrypted_result_ = encryptor_->EncryptBlock(plaintext);
if (encrypted_result_.empty()) {
error_stage_ = "encryption";
error_message_ = "Failed to encrypt data";
return false;
}
// If the sequence was interrupted by a DBPSUnsupportedException at any point, use per block encryption.
// Set the encryption type to per block.
encryption_metadata_[ENCRYPTION_MODE] = ENCRYPTION_PER_BLOCK;
encryption_metadata_[DBPS_VERSION_KEY] = DBPS_VERSION;
return true;

} catch (const InvalidInputException& e) {
// Throw the exception so it can be caught by the caller.
throw;
}

// If the sequencer got here, it means the encryption of the values in the typed list finished successfully.
// Set the encryption type to per value
encryption_metadata_[ENCRYPTION_MODE] = ENCRYPTION_PER_VALUE;
Expand Down
1 change: 0 additions & 1 deletion src/server/encryptors/basic_encryptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
*
* This implementation provides:
* - Block encryption/decryption using XOR with key_id hash (same as current encryption_sequencer)
* - Value encryption/decryption currently throws DBPSUnsupportedException (same as current encryption_sequencer)
*
* This is a simple, default encryption implementation that can be replaced with more
* sophisticated encryption providers (e.g., Protegrity) in the future.
Expand Down
4 changes: 0 additions & 4 deletions src/server/encryptors/dbps_encryptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ class DBPS_EXPORT DBPSEncryptor {
* @param data The plaintext data to encrypt as a vector of bytes
* @return The encrypted data as a vector of bytes
* @throws InvalidInputException if the input data is invalid or empty
* @throws DBPSUnsupportedException if the encryption operation is not supported
*/
virtual std::vector<uint8_t> EncryptBlock(const std::vector<uint8_t>& data) = 0;

Expand All @@ -80,7 +79,6 @@ class DBPS_EXPORT DBPSEncryptor {
* @param data The ciphertext data to decrypt as a vector of bytes
* @return The decrypted data as a vector of bytes
* @throws InvalidInputException if the input data is invalid, empty, or corrupted
* @throws DBPSUnsupportedException if the decryption operation is not supported
*/
virtual std::vector<uint8_t> DecryptBlock(const std::vector<uint8_t>& data) = 0;

Expand All @@ -95,7 +93,6 @@ class DBPS_EXPORT DBPSEncryptor {
* @param typed_list The typed list of values to encrypt (variant type supporting multiple data types)
* @return The encrypted data as a vector of bytes containing the encrypted typed list values
* @throws InvalidInputException if the input data is invalid or empty
* @throws DBPSUnsupportedException if the encryption operation is not supported
*/
virtual std::vector<uint8_t> EncryptValueList(
const TypedListValues& typed_list) = 0;
Expand All @@ -108,7 +105,6 @@ class DBPS_EXPORT DBPSEncryptor {
* @param encrypted_bytes The encrypted data as a vector of bytes containing only the encrypted typed list
* @return The decrypted TypedListValues
* @throws InvalidInputException if the input data is invalid, empty, or corrupted
* @throws DBPSUnsupportedException if the decryption operation is not supported
*/
virtual TypedListValues DecryptValueList(
const std::vector<uint8_t>& encrypted_bytes) = 0;
Expand Down
30 changes: 23 additions & 7 deletions src/server/parquet_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ int CalculateLevelBytesLength(const std::vector<uint8_t>& raw,
total_level_bytes = 0;

} else {
// Unknown page type
throw DBPSUnsupportedException("Unsupported page type: " + page_type);
// Invalid page type
throw InvalidInputException("Invalid page type: " + page_type);
Comment thread
argmarco-tkd marked this conversation as resolved.
}

// Validate that the total level bytes before returning.
Expand Down Expand Up @@ -130,10 +130,10 @@ inline static size_t GetFixedElemSizeOrThrow(Type::type datatype, const std::opt
case Type::UNDEFINED:
return 1;
case Type::BYTE_ARRAY:
throw DBPSUnsupportedException("BYTE_ARRAY is variable-length; not fixed-size");
throw InvalidInputException("BYTE_ARRAY is variable-length; not fixed-size");
default:
throw DBPSUnsupportedException(
"Unsupported datatype: " + std::string(to_string(datatype)));
throw InvalidInputException(
"Invalid datatype. Only fixed-size types are supported: " + std::string(to_string(datatype)));
}
}

Expand All @@ -142,8 +142,16 @@ std::vector<RawValueBytes> SliceValueBytesIntoRawBytes(
Type::type datatype,
const std::optional<int>& datatype_length,
Format::type format) {

// RLE_DICTIONARY is not supported for per-value operations since the values themselves are not present in the data,
// only references to them.
if (format == Format::RLE_DICTIONARY) {
throw DBPSUnsupportedException("Unsupported format: RLE_DICTIONARY is not supported for per-value operations");
}

// TODO(Issue #187): Add support for other encodings.
if (format != Format::PLAIN) {
throw DBPSUnsupportedException("Unsupported format: " + std::string(to_string(format)));
throw DBPSUnsupportedException("On SliceValueBytesIntoRawBytes, unsupported format: " + std::string(to_string(format)));
}

// Variable-length BYTE_ARRAY: parse [4-byte len][bytes...] elements in order.
Expand Down Expand Up @@ -193,8 +201,16 @@ std::vector<uint8_t> CombineRawBytesIntoValueBytes(
Type::type datatype,
const std::optional<int>& datatype_length,
Format::type format) {

// RLE_DICTIONARY is not supported for per-value operations since the values themselves are not present in the data,
// only references to them.
if (format == Format::RLE_DICTIONARY) {
throw DBPSUnsupportedException("Unsupported format: RLE_DICTIONARY is not supported for per-value operations");
}

// TODO(Issue #187): Add support for other encodings.
if (format != Format::PLAIN) {
throw DBPSUnsupportedException("Unsupported format: " + std::string(to_string(format)));
throw DBPSUnsupportedException("On CombineRawBytesIntoValueBytes, unsupported format: " + std::string(to_string(format)));
}

if (datatype == Type::BYTE_ARRAY) {
Expand Down
2 changes: 1 addition & 1 deletion src/server/parquet_utils_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ TEST(ParquetUtils, CalculateLevelBytesLength_UnknownPageType) {
AttributesMap attribs = {
{"page_type", std::string("UNKNOWN_PAGE_TYPE")}
};
EXPECT_THROW(CalculateLevelBytesLength(raw, attribs), DBPSUnsupportedException);
EXPECT_THROW(CalculateLevelBytesLength(raw, attribs), InvalidInputException);
}

TEST(ParquetUtils, CalculateLevelBytesLength_InvalidTotalSize) {
Expand Down