Skip to content

Commit 3d793f0

Browse files
committed
- Updates from review comments.
1 parent 02023d2 commit 3d793f0

9 files changed

Lines changed: 66 additions & 31 deletions

src/common/dbpa_interface.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class DBPS_EXPORT EncryptionResult {
6464
virtual bool success() const = 0;
6565

6666
// Encryption metadata (valid when success() == true)
67+
// Map of string key-value pairs containing any extra parameters used during encryption that are needed for decryption,
68+
// for example, the encryption_algorithm_version used.
6769
virtual const std::optional<std::map<std::string, std::string>> encryption_metadata() const = 0;
6870

6971
// Error details (valid when success() == false).
@@ -135,7 +137,12 @@ class DBPS_EXPORT DataBatchProtectionAgentInterface {
135137
span<const uint8_t> ciphertext,
136138
std::map<std::string, std::string> encoding_attributes) = 0;
137139

138-
virtual const std::optional<std::map<std::string, std::string>> EncryptionMetadata() const {
140+
/* Returns the encryption metadata provided during the class init() call.
141+
* The encryption metadata is a map of string key-value pairs and is defined only for Decrypt usage.
142+
* This metadata map is the one returned by the EncryptionResult.encryption_metadata() during the Encrypt call and indicates
143+
* any extra parameters used during encryption that are needed for decryption, for example, the encryption_algorithm_version used.
144+
*/
145+
virtual const std::optional<std::map<std::string, std::string>> EncryptionMetadata() const {
139146
return column_encryption_metadata_;
140147
}
141148

src/common/dbpa_local.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ std::unique_ptr<EncryptionResult> LocalDataBatchProtectionAgent::Encrypt(
198198
column_key_id_,
199199
user_id_,
200200
app_context_,
201-
{}
201+
{} // encryption_metadata, which is empty for the Encryption call.
202202
);
203203

204204
// Convert plaintext span to vector for the sequencer

src/common/dbpa_local_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
using namespace dbps::external;
2424

2525
namespace {
26-
const std::map<std::string, std::string> VALID_ENCRYPTION_METADATA = {{"dbps_version", "v0.01"}};
26+
const std::map<std::string, std::string> VALID_ENCRYPTION_METADATA = {{"dbps_agent_version", "v0.01"}};
2727
}
2828

2929
// Test fixture for LocalDataBatchProtectionAgent tests
@@ -121,7 +121,7 @@ TEST_F(LocalDataBatchProtectionAgentTest, RoundTripEncryptDecrypt) {
121121
auto encryption_metadata = encrypt_result->encryption_metadata();
122122
ASSERT_TRUE(encryption_metadata.has_value());
123123
ASSERT_EQ(1, encryption_metadata->size());
124-
ASSERT_TRUE(encryption_metadata->at("dbps_version").length() > 0); // Non-empty string
124+
ASSERT_TRUE(encryption_metadata->at("dbps_agent_version").length() > 0); // Non-empty string
125125

126126
// Get the ciphertext
127127
auto ciphertext_span = encrypt_result->ciphertext();

src/common/dbpa_remote.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ bool RemoteEncryptionResult::success() const {
5050
const std::optional<std::map<std::string, std::string>> RemoteEncryptionResult::encryption_metadata() const {
5151
if (!cached_encryption_metadata_.has_value() && response_ && response_->Success()) {
5252
const auto& response_attrs = response_->GetResponseAttributes();
53+
// For the RemoteEncryptionResult, encryption_metadata_ is forwarded from the API response.
54+
// The attribute in the API response is also named encryption_metadata.
55+
// If the API reponse is empty, the cached value is set to NULL for compatibility with the class interface.
5356
if (!response_attrs.encryption_metadata_.empty()) {
5457
cached_encryption_metadata_ = response_attrs.encryption_metadata_;
5558
} else {

src/common/json_request.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ std::optional<int> SafeParseToInt(const std::string& str) {
6969
static std::optional<crow::json::rvalue> SafeLoadJsonBody(const std::string& json_string) {
7070
auto json_body = crow::json::load(json_string);
7171
if (!json_body || json_body.t() == crow::json::type::Null) {
72+
CROW_LOG_ERROR << "Invalid JSON body: " << json_string;
7273
return std::nullopt;
7374
}
7475
return json_body;

src/common/json_request_test.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const std::string VALID_DECRYPT_JSON = R"({
142142
},
143143
"application_context": "{\"user_id\": \"user456\"}",
144144
"encryption_metadata": {
145-
"dbps_version": "v0.01"
145+
"dbps_agent_version": "v0.01"
146146
},
147147
"debug": {
148148
"reference_id": "ref789",
@@ -358,7 +358,7 @@ TEST(JsonRequest, DecryptJsonRequestValidParse) {
358358

359359
// Verify encryption_metadata is parsed correctly
360360
ASSERT_EQ(1, request.encryption_metadata_.size());
361-
ASSERT_EQ("v0.01", request.encryption_metadata_.at("dbps_version"));
361+
ASSERT_EQ("v0.01", request.encryption_metadata_.at("dbps_agent_version"));
362362

363363
ASSERT_TRUE(request.IsValid());
364364
ASSERT_EQ("", request.GetValidationError());
@@ -600,7 +600,7 @@ const std::string VALID_ENCRYPT_RESPONSE_JSON = R"({
600600
"pretty_printed_value": "ENCRYPTED_test@example.com"
601601
},
602602
"encryption_metadata": {
603-
"dbps_version": "v0.01"
603+
"dbps_agent_version": "v0.01"
604604
}
605605
})";
606606

@@ -640,7 +640,7 @@ TEST(JsonRequest, EncryptJsonResponseValidParse) {
640640

641641
// Verify encryption_metadata is parsed correctly
642642
ASSERT_EQ(1, response.encryption_metadata_.size());
643-
ASSERT_EQ("v0.01", response.encryption_metadata_.at("dbps_version"));
643+
ASSERT_EQ("v0.01", response.encryption_metadata_.at("dbps_agent_version"));
644644

645645
ASSERT_TRUE(response.IsValid());
646646
ASSERT_EQ("", response.GetValidationError());
@@ -749,7 +749,7 @@ TEST(JsonRequest, EncryptJsonResponseToJson) {
749749
response.reference_id_ = "ref456";
750750
response.encrypted_compression_ = CompressionCodec::GZIP;
751751
response.encrypted_value_ = StringToBinary("ENCRYPTED_data");
752-
response.encryption_metadata_["dbps_version"] = "v0.01";
752+
response.encryption_metadata_["dbps_agent_version"] = "v0.01";
753753

754754
ASSERT_TRUE(response.IsValid());
755755

@@ -763,7 +763,7 @@ TEST(JsonRequest, EncryptJsonResponseToJson) {
763763

764764
// Verify encryption_metadata is serialized correctly
765765
ASSERT_TRUE(json_string.find("encryption_metadata") != std::string::npos);
766-
ASSERT_TRUE(json_string.find("dbps_version") != std::string::npos);
766+
ASSERT_TRUE(json_string.find("dbps_agent_version") != std::string::npos);
767767
ASSERT_TRUE(json_string.find("v0.01") != std::string::npos);
768768
}
769769

src/scripts/dbpa_remote_testapp.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ template <typename T>
3737
using span = tcb::span<T>;
3838

3939
namespace {
40-
const std::map<std::string, std::string> VALID_ENCRYPTION_METADATA = {{"dbps_version", "v0.01_unittest"}};
40+
const std::map<std::string, std::string> VALID_ENCRYPTION_METADATA = {{"dbps_agent_version", "v0.01_unittest"}};
4141
const std::string SEQUENCER_ENCRYPTION_METADATA_VERSION = "v0.01";
4242
}
4343

@@ -203,20 +203,20 @@ class DBPARemoteTestApp {
203203

204204
// Verify encryption metadata
205205
auto encryption_metadata = encrypt_result->encryption_metadata();
206-
if (!encryption_metadata || encryption_metadata->find("dbps_version") == encryption_metadata->end()) {
206+
if (!encryption_metadata || encryption_metadata->find("dbps_agent_version") == encryption_metadata->end()) {
207207
std::cout << " ERROR: Encryption metadata verification failed" << std::endl;
208208
all_succeeded = false;
209209
continue;
210210
}
211-
if (encryption_metadata->at("dbps_version") != SEQUENCER_ENCRYPTION_METADATA_VERSION) {
211+
if (encryption_metadata->at("dbps_agent_version") != SEQUENCER_ENCRYPTION_METADATA_VERSION) {
212212
std::cout << " ERROR: Encryption metadata version mismatch" << std::endl;
213213
std::cout << " Expected: " << SEQUENCER_ENCRYPTION_METADATA_VERSION << std::endl;
214-
std::cout << " Got: " << encryption_metadata->at("dbps_version") << std::endl;
214+
std::cout << " Got: " << encryption_metadata->at("dbps_agent_version") << std::endl;
215215
all_succeeded = false;
216216
continue;
217217
}
218218
std::cout << " OK: Encryption metadata verified" << std::endl;
219-
std::cout << " dbps_version: " << encryption_metadata->at("dbps_version") << std::endl;
219+
std::cout << " dbps_agent_version: " << encryption_metadata->at("dbps_agent_version") << std::endl;
220220

221221
std::cout << " OK: Encrypted (" << encrypt_result->size() << " bytes)" << std::endl;
222222
std::cout << " OK: Ciphertext size: " << encrypt_result->size() << " bytes" << std::endl;

src/server/encryption_sequencer.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ using namespace dbps::external;
2929
using namespace dbps::enum_utils;
3030

3131
namespace {
32-
constexpr const char* DBPS_VERSION_KEY = "dbps_version";
32+
constexpr const char* DBPS_VERSION_KEY = "dbps_agent_version";
3333
constexpr const char* DBPS_VERSION_VALUE = "v0.01";
3434
}
3535

@@ -394,7 +394,7 @@ bool DataBatchEncryptionSequencer::ConvertAndDecrypt(const std::vector<uint8_t>&
394394

395395
// TODO: Make server version check a Sequencer error and stop processing.
396396
//
397-
// Check encryption_metadata for dbps_version
397+
// Check encryption_metadata for dbps_agent_version
398398
//
399399
// The DBPS server version check during Decrypt is to future-proof against changes on the Encryption process.
400400
// The Encryption process could change due to updates on the payload decoding, updates on fallback encryption methods, or other changes,
@@ -406,10 +406,10 @@ bool DataBatchEncryptionSequencer::ConvertAndDecrypt(const std::vector<uint8_t>&
406406
error_message_ = "encryption_metadata must contain key '" + std::string(DBPS_VERSION_KEY) + "'";
407407
return false;
408408
} else if (it->second.find(DBPS_VERSION_VALUE) != 0) {
409-
std::cerr << "ERROR: EncryptionSequencer - encryption_metadata['" << DBPS_VERSION_KEY << "'] must start with '"
409+
std::cerr << "ERROR: EncryptionSequencer - encryption_metadata['" << DBPS_VERSION_KEY << "'] must match '"
410410
<< DBPS_VERSION_VALUE << "', but got '" << it->second << "'" << std::endl;
411411
error_stage_ = "decrypt_version_check";
412-
error_message_ = "encryption_metadata['" + std::string(DBPS_VERSION_KEY) + "'] must start with '" + std::string(DBPS_VERSION_VALUE) + "'";
412+
error_message_ = "encryption_metadata['" + std::string(DBPS_VERSION_KEY) + "'] must match '" + std::string(DBPS_VERSION_VALUE) + "'";
413413
return false;
414414
}
415415

src/server/encryption_sequencer_test.cpp

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,31 @@ TEST(EncryptionSequencer, InputValidation) {
252252
EXPECT_FALSE(result) << "Empty key_id test should have failed";
253253
EXPECT_EQ(sequencer.error_stage_, "validation") << "Wrong error stage for empty key_id";
254254
}
255-
255+
256+
// Test 4: Missing encryption_metadata
257+
{
258+
DataBatchEncryptionSequencer sequencer(
259+
"test_column", Type::BYTE_ARRAY, std::nullopt, CompressionCodec::UNCOMPRESSED, Format::PLAIN, {{"page_type", "DICTIONARY_PAGE"}}, CompressionCodec::UNCOMPRESSED, "test_key", "test_user", "{}",
260+
{} // encryption_metadata, setting it to empty map.
261+
);
262+
bool result = sequencer.ConvertAndDecrypt(HELLO_WORLD_DATA);
263+
EXPECT_FALSE(result) << "Missing encryption_metadata test should have failed";
264+
EXPECT_EQ(sequencer.error_stage_, "decrypt_version_check") << "Wrong error stage for missing encryption_metadata";
265+
EXPECT_TRUE(sequencer.error_message_.find("encryption_metadata must contain key") != std::string::npos) << "Wrong error message for missing encryption_metadata";
266+
}
267+
268+
// Test 5: Incorrect encryption_metadata version
269+
{
270+
DataBatchEncryptionSequencer sequencer(
271+
"test_column", Type::BYTE_ARRAY, std::nullopt, CompressionCodec::UNCOMPRESSED, Format::PLAIN, {{"page_type", "DICTIONARY_PAGE"}}, CompressionCodec::UNCOMPRESSED, "test_key", "test_user", "{}",
272+
{{"dbps_agent_version", "v0.09"}} // encryption_metadata, setting it to incorrect version.
273+
);
274+
bool result = sequencer.ConvertAndDecrypt(HELLO_WORLD_DATA);
275+
EXPECT_FALSE(result) << "Incorrect encryption_metadata version test should have failed";
276+
EXPECT_EQ(sequencer.error_stage_, "decrypt_version_check") << "Wrong error stage for incorrect encryption_metadata version";
277+
EXPECT_TRUE(sequencer.error_message_.find("must match") != std::string::npos) << "Wrong error message for incorrect encryption_metadata version";
278+
}
279+
256280
}
257281

258282
// Test round-trip encryption/decryption
@@ -267,8 +291,8 @@ TEST(EncryptionSequencer, RoundTripEncryption) {
267291
bool encrypt_result = sequencer.ConvertAndEncrypt(HELLO_WORLD_DATA);
268292
ASSERT_TRUE(encrypt_result) << "Round trip encryption failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
269293

270-
// Decrypt the encrypted result - need encryption_metadata with dbps_version
271-
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_version").length() > 0);
294+
// Decrypt the encrypted result - need encryption_metadata with dbps_agent_version
295+
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_agent_version").length() > 0);
272296
bool decrypt_result = sequencer.ConvertAndDecrypt(sequencer.encrypted_result_);
273297
ASSERT_TRUE(decrypt_result) << "Round trip decryption failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
274298

@@ -286,8 +310,8 @@ TEST(EncryptionSequencer, RoundTripEncryption) {
286310
bool encrypt_result = sequencer.ConvertAndEncrypt(BINARY_DATA); // Binary data: 0x00, 0x01, 0x02, 0x03, 0x04, 0x05
287311
ASSERT_TRUE(encrypt_result) << "Binary round trip encryption failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
288312

289-
// Decrypt the encrypted result - need encryption_metadata with dbps_version
290-
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_version").length() > 0);
313+
// Decrypt the encrypted result - need encryption_metadata with dbps_agent_version
314+
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_agent_version").length() > 0);
291315
bool decrypt_result = sequencer.ConvertAndDecrypt(sequencer.encrypted_result_);
292316
ASSERT_TRUE(decrypt_result) << "Binary round trip decryption failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
293317

@@ -307,8 +331,8 @@ TEST(EncryptionSequencer, RoundTripEncryption) {
307331
bool encrypt_result = sequencer.ConvertAndEncrypt(SINGLE_CHAR_DATA);
308332
ASSERT_TRUE(encrypt_result) << "Single char round trip encryption failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
309333

310-
// Decrypt the encrypted result - need encryption_metadata with dbps_version
311-
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_version").length() > 0);
334+
// Decrypt the encrypted result - need encryption_metadata with dbps_agent_version
335+
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_agent_version").length() > 0);
312336
bool decrypt_result = sequencer.ConvertAndDecrypt(sequencer.encrypted_result_);
313337
ASSERT_TRUE(decrypt_result) << "Single char round trip decryption failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
314338

@@ -335,9 +359,9 @@ TEST(EncryptionSequencer, RoundTripEncryption) {
335359
// Key-aware XOR encryption should produce different results for different keys
336360
EXPECT_NE(sequencer1.encrypted_result_, sequencer2.encrypted_result_);
337361

338-
// But both should decrypt back to the same original - need encryption_metadata with dbps_version
339-
ASSERT_TRUE(sequencer1.encryption_metadata_.size() > 0 && sequencer1.encryption_metadata_.at("dbps_version").length() > 0);
340-
ASSERT_TRUE(sequencer2.encryption_metadata_.size() > 0 && sequencer2.encryption_metadata_.at("dbps_version").length() > 0);
362+
// But both should decrypt back to the same original - need encryption_metadata with dbps_agent_version
363+
ASSERT_TRUE(sequencer1.encryption_metadata_.size() > 0 && sequencer1.encryption_metadata_.at("dbps_agent_version").length() > 0);
364+
ASSERT_TRUE(sequencer2.encryption_metadata_.size() > 0 && sequencer2.encryption_metadata_.at("dbps_agent_version").length() > 0);
341365
bool decrypt1 = sequencer1.ConvertAndDecrypt(sequencer1.encrypted_result_);
342366
bool decrypt2 = sequencer2.ConvertAndDecrypt(sequencer2.encrypted_result_);
343367

@@ -376,8 +400,8 @@ TEST(EncryptionSequencer, ResultStorage) {
376400
bool encrypt_result = sequencer.ConvertAndEncrypt(HELLO_WORLD_DATA);
377401
ASSERT_TRUE(encrypt_result) << "Result storage decryption test failed during encryption";
378402

379-
// Then decrypt it - need encryption_metadata with dbps_version
380-
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_version").length() > 0);
403+
// Then decrypt it - need encryption_metadata with dbps_agent_version
404+
ASSERT_TRUE(sequencer.encryption_metadata_.size() > 0 && sequencer.encryption_metadata_.at("dbps_agent_version").length() > 0);
381405
bool decrypt_result = sequencer.ConvertAndDecrypt(sequencer.encrypted_result_);
382406
ASSERT_TRUE(decrypt_result) << "Result storage decryption test failed: " << sequencer.error_stage_ << " - " << sequencer.error_message_;
383407

0 commit comments

Comments
 (0)