Skip to content

Commit 686b38f

Browse files
committed
Add test_read_subset_of_encrypted_columns_with_plaintext_footer
1 parent c765177 commit 686b38f

File tree

3 files changed

+41
-20
lines changed

3 files changed

+41
-20
lines changed

parquet/src/encryption/decrypt.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,11 @@ impl FileDecryptor {
614614
Ok(self.footer_decryptor.clone())
615615
}
616616

617+
/// Returns true if the column is encrypted with a column key.
618+
pub(crate) fn is_column_encrypted(&self, column_name: &str) -> bool {
619+
self.decryption_properties.column_keys().0.contains(&column_name.to_string())
620+
}
621+
617622
/// Verify the signature of the footer
618623
pub(crate) fn verify_plaintext_footer_signature(&self, plaintext_footer: &[u8]) -> Result<()> {
619624
// Plaintext footer format is: [plaintext metadata, nonce, authentication tag]

parquet/src/file/metadata/thrift/encryption.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,16 @@ fn row_group_from_encrypted_thrift(
144144
}
145145
Some(ColumnCryptoMetaData::ENCRYPTION_WITH_COLUMN_KEY(crypto_metadata)) => {
146146
let column_name = crypto_metadata.path_in_schema.join(".");
147-
decryptor.get_column_metadata_decryptor(
148-
column_name.as_str(),
149-
crypto_metadata.key_metadata.as_deref(),
150-
)?
147+
if decryptor.is_column_encrypted(column_name.as_str()) {
148+
decryptor.get_column_metadata_decryptor(
149+
column_name.as_str(),
150+
crypto_metadata.key_metadata.as_deref(),
151+
)?
152+
} else {
153+
// We don't have the key for this column, so we can't decrypt it's metadata.
154+
columns.push(c);
155+
continue;
156+
}
151157
}
152158
Some(ColumnCryptoMetaData::ENCRYPTION_WITH_FOOTER_KEY) => {
153159
decryptor.get_footer_decryptor()?

parquet/tests/encryption/encryption.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -720,17 +720,18 @@ fn test_write_uniform_encryption_plaintext_footer() {
720720
}
721721

722722
#[test]
723-
pub fn test_row_group_statistics_plaintext_encrypted_write() {
723+
pub fn test_non_uniform_plaintext_encryption_behaviour() {
724724
let footer_key = b"0123456789012345".to_vec(); // 128bit/16
725725
let column_key = b"1234567890123450".to_vec();
726726

727-
let decryption_properties = FileDecryptionProperties::builder(footer_key.clone())
727+
let encryption_properties = FileEncryptionProperties::builder(footer_key.clone())
728+
.with_plaintext_footer(true)
728729
.with_column_key("x", column_key.clone())
730+
.with_column_key("y", column_key.clone())
729731
.build()
730732
.unwrap();
731733

732-
let encryption_properties = FileEncryptionProperties::builder(footer_key)
733-
.with_plaintext_footer(true)
734+
let decryption_properties = FileDecryptionProperties::builder(footer_key.clone())
734735
.with_column_key("x", column_key.clone())
735736
.build()
736737
.unwrap();
@@ -739,16 +740,21 @@ pub fn test_row_group_statistics_plaintext_encrypted_write() {
739740
.with_file_encryption_properties(encryption_properties)
740741
.build();
741742

742-
// Write encrypted data with plaintext footer
743+
// Write partly encrypted data with plaintext footer
743744
let values = Int32Array::from(vec![8, 3, 4, 19, 5]);
745+
let values = Arc::new(values);
744746
let schema = Arc::new(Schema::new(vec![
745747
Field::new("x", values.data_type().clone(), true),
746748
Field::new("y", values.data_type().clone(), true),
749+
Field::new("z", values.data_type().clone(), true),
747750
]));
748-
749-
let values = Arc::new(values);
750-
let record_batches =
751-
vec![RecordBatch::try_new(schema.clone(), vec![values.clone(), values.clone()]).unwrap()];
751+
let record_batches = vec![
752+
RecordBatch::try_new(
753+
schema.clone(),
754+
vec![values.clone(), values.clone(), values.clone()],
755+
)
756+
.unwrap(),
757+
];
752758

753759
let temp_file = tempfile::tempfile().unwrap();
754760
let mut writer = ArrowWriter::try_new(&temp_file, schema, Some(props)).unwrap();
@@ -773,28 +779,32 @@ pub fn test_row_group_statistics_plaintext_encrypted_write() {
773779
}
774780
};
775781

776-
// Check column statistics that are produced on write are complete
782+
// Check column statistics produced at write time are available in full
777783
let row_group = metadata.row_group(0);
778784
check_column_stats(row_group.column(0), true);
779785
check_column_stats(row_group.column(1), true);
786+
check_column_stats(row_group.column(2), true);
780787

781788
// Check column statistics are read given plaintext footer and available decryption properties
782789
let options =
783790
ArrowReaderOptions::default().with_file_decryption_properties(decryption_properties);
784-
let reader_metadata = ArrowReaderMetadata::load(&temp_file, options.clone()).unwrap();
791+
let reader_metadata = ArrowReaderMetadata::load(&temp_file, options).unwrap();
785792
let metadata = reader_metadata.metadata();
786793
let row_group = metadata.row_group(0);
787-
// Reader reads encrypted stats since decryption properties are provided
794+
// Reader can read plaintext from the unencrypted column
795+
// and column x for which the key is provided
788796
check_column_stats(row_group.column(0), true);
789-
check_column_stats(row_group.column(1), true);
797+
check_column_stats(row_group.column(1), false);
798+
check_column_stats(row_group.column(2), true);
790799

791800
let options = ArrowReaderOptions::default();
792-
let reader_metadata = ArrowReaderMetadata::load(&temp_file, options.clone()).unwrap();
801+
let reader_metadata = ArrowReaderMetadata::load(&temp_file, options).unwrap();
793802
let metadata = reader_metadata.metadata();
794803
let row_group = metadata.row_group(0);
795-
// Reader can't read encrypted stats since decryption properties are not provided
804+
// Reader can only read plaintext from the unencrypted column if no key is provided
796805
check_column_stats(row_group.column(0), false);
797-
check_column_stats(row_group.column(1), true);
806+
check_column_stats(row_group.column(1), false);
807+
check_column_stats(row_group.column(2), true);
798808
}
799809

800810
#[test]

0 commit comments

Comments
 (0)