1717
1818use crate :: encryption:: ciphers:: { BlockEncryptor , RingGcmBlockEncryptor } ;
1919use crate :: errors:: Result ;
20+ use crate :: file:: column_crypto_metadata:: { ColumnCryptoMetaData , EncryptionWithColumnKey } ;
21+ use crate :: schema:: types:: ColumnDescPtr ;
2022use crate :: thrift:: TSerializable ;
2123use ring:: rand:: { SecureRandom , SystemRandom } ;
2224use std:: collections:: HashMap ;
@@ -51,7 +53,7 @@ impl EncryptionKey {
5153pub struct FileEncryptionProperties {
5254 encrypt_footer : bool ,
5355 footer_key : EncryptionKey ,
54- column_keys : HashMap < Vec < u8 > , EncryptionKey > ,
56+ column_keys : HashMap < String , EncryptionKey > ,
5557 aad_prefix : Option < Vec < u8 > > ,
5658 store_aad_prefix : bool ,
5759}
@@ -80,7 +82,7 @@ impl FileEncryptionProperties {
8082
8183pub struct EncryptionPropertiesBuilder {
8284 footer_key : EncryptionKey ,
83- column_keys : HashMap < Vec < u8 > , EncryptionKey > ,
85+ column_keys : HashMap < String , EncryptionKey > ,
8486 aad_prefix : Option < Vec < u8 > > ,
8587 encrypt_footer : bool ,
8688 store_aad_prefix : bool ,
@@ -107,8 +109,8 @@ impl EncryptionPropertiesBuilder {
107109 self
108110 }
109111
110- pub fn with_column_key ( mut self , column_name : Vec < u8 > , encryption_key : EncryptionKey ) -> Self {
111- self . column_keys . insert ( column_name , encryption_key) ;
112+ pub fn with_column_key ( mut self , column_path : String , encryption_key : EncryptionKey ) -> Self {
113+ self . column_keys . insert ( column_path , encryption_key) ;
112114 self
113115 }
114116
@@ -179,18 +181,17 @@ impl FileEncryptor {
179181 if self . properties . column_keys . is_empty ( ) {
180182 return self . get_footer_encryptor ( ) ;
181183 }
182- // TODO: Column paths should be stored as String
183- let column_path = column_path. as_bytes ( ) ;
184184 match self . properties . column_keys . get ( column_path) {
185185 None => todo ! ( "Handle unencrypted columns" ) ,
186186 Some ( column_key) => Ok ( Box :: new ( RingGcmBlockEncryptor :: new ( column_key. key ( ) ) ?) ) ,
187187 }
188188 }
189189}
190190
191+ /// Encrypt a Thrift serializable object
191192pub ( crate ) fn encrypt_object < T : TSerializable , W : Write > (
192- object : T ,
193- encryptor : & FileEncryptor ,
193+ object : & T ,
194+ encryptor : & mut Box < dyn BlockEncryptor > ,
194195 sink : & mut W ,
195196 module_aad : & [ u8 ] ,
196197) -> Result < ( ) > {
@@ -200,11 +201,46 @@ pub(crate) fn encrypt_object<T: TSerializable, W: Write>(
200201 object. write_to_out_protocol ( & mut unencrypted_protocol) ?;
201202 }
202203
203- // TODO: Get correct encryptor (footer vs column, data vs metadata)
204- let encrypted_buffer = encryptor
205- . get_footer_encryptor ( ) ?
206- . encrypt ( buffer. as_ref ( ) , module_aad) ;
204+ let encrypted_buffer = encryptor. encrypt ( buffer. as_ref ( ) , module_aad) ?;
207205
208206 sink. write_all ( & encrypted_buffer) ?;
209207 Ok ( ( ) )
210208}
209+
210+ /// Encrypt a Thrift serializable object
211+ pub ( crate ) fn encrypt_object_to_vec < T : TSerializable > (
212+ object : & T ,
213+ encryptor : & mut Box < dyn BlockEncryptor > ,
214+ module_aad : & [ u8 ] ,
215+ ) -> Result < Vec < u8 > > {
216+ let mut buffer: Vec < u8 > = vec ! [ ] ;
217+ {
218+ let mut unencrypted_protocol = TCompactOutputProtocol :: new ( & mut buffer) ;
219+ object. write_to_out_protocol ( & mut unencrypted_protocol) ?;
220+ }
221+
222+ encryptor. encrypt ( buffer. as_ref ( ) , module_aad)
223+ }
224+
225+ /// Get the crypto metadata for a column from the file encryption properties
226+ pub fn get_column_crypto_metadata (
227+ properties : & FileEncryptionProperties ,
228+ column : & ColumnDescPtr ,
229+ ) -> Option < ColumnCryptoMetaData > {
230+ if properties. column_keys . is_empty ( ) {
231+ // Uniform encryption
232+ Some ( ColumnCryptoMetaData :: EncryptionWithFooterKey )
233+ } else {
234+ match properties. column_keys . get ( & column. path ( ) . string ( ) ) {
235+ // Column is not encrypted
236+ None => None ,
237+ // Column is encrypted with a column specific key
238+ Some ( encryption_key) => Some ( ColumnCryptoMetaData :: EncryptionWithColumnKey (
239+ EncryptionWithColumnKey {
240+ path_in_schema : column. path ( ) . parts ( ) . to_vec ( ) ,
241+ key_metadata : encryption_key. key_metadata . clone ( ) ,
242+ } ,
243+ ) ) ,
244+ }
245+ }
246+ }
0 commit comments