@@ -35,7 +35,10 @@ use crate::file::{
35
35
36
36
use crate :: schema:: types:: { self , SchemaDescriptor } ;
37
37
38
- use crate :: file:: { encryption:: { decrypt_module, parquet_magic, ParquetEncryptionConfig , PARQUET_KEY_HASH_LENGTH , ParquetEncryptionKey , ParquetEncryptionKeyInfo , RandomFileIdentifier , AAD_FILE_UNIQUE_SIZE } , PARQUET_MAGIC_ENCRYPTED_FOOTER_CUBE , PARQUET_MAGIC_UNSUPPORTED_PARE } ;
38
+ use crate :: file:: { encryption:: { decrypt_module, ParquetEncryptionConfig , ParquetEncryptionMode ,
39
+ ParquetEncryptionKey ,
40
+ PARQUET_KEY_HASH_LENGTH , RandomFileIdentifier , AAD_FILE_UNIQUE_SIZE } ,
41
+ PARQUET_MAGIC_ENCRYPTED_FOOTER_CUBE , PARQUET_MAGIC_UNSUPPORTED_PARE } ;
39
42
40
43
fn select_key ( encryption_config : & ParquetEncryptionConfig , key_metadata : & Option < Vec < u8 > > ) -> Result < ParquetEncryptionKey > {
41
44
if let Some ( key_id) = key_metadata {
@@ -44,10 +47,15 @@ fn select_key(encryption_config: &ParquetEncryptionConfig, key_metadata: &Option
44
47
}
45
48
let mut key_id_arr = [ 0u8 ; PARQUET_KEY_HASH_LENGTH ] ;
46
49
key_id_arr. copy_from_slice ( & key_id) ;
47
- let read_keys: & [ ParquetEncryptionKeyInfo ] = encryption_config. read_keys ( ) ;
48
- for key_info in read_keys {
49
- if key_info. key . compute_key_hash ( ) == key_id_arr {
50
- return Ok ( key_info. key )
50
+ let read_keys: & [ ParquetEncryptionMode ] = encryption_config. read_keys ( ) ;
51
+ for mode in read_keys {
52
+ match mode {
53
+ ParquetEncryptionMode :: Unencrypted => { } ,
54
+ ParquetEncryptionMode :: FooterEncrypted ( key_info) => {
55
+ if key_info. key . compute_key_hash ( ) == key_id_arr {
56
+ return Ok ( key_info. key )
57
+ }
58
+ }
51
59
}
52
60
}
53
61
return Err ( general_err ! ( "Parquet file is encrypted with an unknown or out-of-rotation key" ) ) ;
@@ -81,18 +89,28 @@ pub fn parse_metadata<R: ChunkReader>(chunk_reader: &R, encryption_config: &Opti
81
89
default_end_reader. read_exact ( & mut default_len_end_buf) ?;
82
90
83
91
// check this is indeed a parquet file
92
+ let encrypted_footer: bool ;
84
93
{
94
+ // and check that its encryption setting conceivably matches our encryption_config (but without yet checking keys)
85
95
let trailing_magic: & [ u8 ] = & default_len_end_buf[ default_end_len - 4 ..] ;
86
- if trailing_magic != parquet_magic ( encryption_config. is_some ( ) ) {
87
- if trailing_magic == PARQUET_MAGIC {
88
- return Err ( general_err ! ( "Invalid Parquet file in encrypted mode. File (or at least the Parquet footer) is not encrypted" ) ) ;
89
- } else if trailing_magic == PARQUET_MAGIC_ENCRYPTED_FOOTER_CUBE {
96
+ if trailing_magic == PARQUET_MAGIC {
97
+ if let Some ( config) = encryption_config {
98
+ if !config. read_keys ( ) . iter ( ) . any ( |m| matches ! ( m, ParquetEncryptionMode :: Unencrypted ) ) {
99
+ return Err ( general_err ! ( "Invalid Parquet file in encrypted mode. File (or at least the Parquet footer) is not encrypted" ) ) ;
100
+ }
101
+ }
102
+ encrypted_footer = false ;
103
+ } else if trailing_magic == PARQUET_MAGIC_ENCRYPTED_FOOTER_CUBE {
104
+ let has_keys = encryption_config. as_ref ( ) . map_or ( false ,
105
+ |config| config. read_keys ( ) . iter ( ) . any ( |m| matches ! ( m, ParquetEncryptionMode :: FooterEncrypted ( _) ) ) ) ;
106
+ if !has_keys {
90
107
return Err ( general_err ! ( "Invalid Parquet file in unencrypted mode. File is encrypted" ) ) ;
91
- } else if trailing_magic == PARQUET_MAGIC_UNSUPPORTED_PARE {
92
- return Err ( general_err ! ( "Unsupported Parquet file. File is encrypted with the standard PARE encryption format" ) ) ;
93
- } else {
94
- return Err ( general_err ! ( "Invalid Parquet file. Corrupt footer" ) ) ;
95
108
}
109
+ encrypted_footer = true ;
110
+ } else if trailing_magic == PARQUET_MAGIC_UNSUPPORTED_PARE {
111
+ return Err ( general_err ! ( "Unsupported Parquet file. File is encrypted with the standard PARE encryption format" ) ) ;
112
+ } else {
113
+ return Err ( general_err ! ( "Invalid Parquet file. Corrupt footer" ) ) ;
96
114
}
97
115
}
98
116
@@ -135,7 +153,8 @@ pub fn parse_metadata<R: ChunkReader>(chunk_reader: &R, encryption_config: &Opti
135
153
let returned_encryption_key: Option < ParquetEncryptionKey > ;
136
154
137
155
let random_file_identifier: Option < RandomFileIdentifier > ;
138
- if let Some ( encryption_config) = encryption_config {
156
+ if encrypted_footer {
157
+ let encryption_config: & ParquetEncryptionConfig = encryption_config. as_ref ( ) . unwrap ( ) ;
139
158
let file_crypto_metadata = {
140
159
let mut prot = TCompactInputProtocol :: new ( & mut metadata_read) ;
141
160
TFileCryptoMetaData :: read_from_in_protocol ( & mut prot)
0 commit comments