17
17
18
18
use crate :: encryption:: ciphers:: { BlockEncryptor , RingGcmBlockEncryptor } ;
19
19
use crate :: errors:: Result ;
20
+ use crate :: file:: column_crypto_metadata:: { ColumnCryptoMetaData , EncryptionWithColumnKey } ;
21
+ use crate :: schema:: types:: ColumnDescPtr ;
20
22
use crate :: thrift:: TSerializable ;
21
23
use ring:: rand:: { SecureRandom , SystemRandom } ;
22
24
use std:: collections:: HashMap ;
@@ -51,7 +53,7 @@ impl EncryptionKey {
51
53
pub struct FileEncryptionProperties {
52
54
encrypt_footer : bool ,
53
55
footer_key : EncryptionKey ,
54
- column_keys : HashMap < Vec < u8 > , EncryptionKey > ,
56
+ column_keys : HashMap < String , EncryptionKey > ,
55
57
aad_prefix : Option < Vec < u8 > > ,
56
58
store_aad_prefix : bool ,
57
59
}
@@ -80,7 +82,7 @@ impl FileEncryptionProperties {
80
82
81
83
pub struct EncryptionPropertiesBuilder {
82
84
footer_key : EncryptionKey ,
83
- column_keys : HashMap < Vec < u8 > , EncryptionKey > ,
85
+ column_keys : HashMap < String , EncryptionKey > ,
84
86
aad_prefix : Option < Vec < u8 > > ,
85
87
encrypt_footer : bool ,
86
88
store_aad_prefix : bool ,
@@ -107,8 +109,8 @@ impl EncryptionPropertiesBuilder {
107
109
self
108
110
}
109
111
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) ;
112
114
self
113
115
}
114
116
@@ -179,18 +181,17 @@ impl FileEncryptor {
179
181
if self . properties . column_keys . is_empty ( ) {
180
182
return self . get_footer_encryptor ( ) ;
181
183
}
182
- // TODO: Column paths should be stored as String
183
- let column_path = column_path. as_bytes ( ) ;
184
184
match self . properties . column_keys . get ( column_path) {
185
185
None => todo ! ( "Handle unencrypted columns" ) ,
186
186
Some ( column_key) => Ok ( Box :: new ( RingGcmBlockEncryptor :: new ( column_key. key ( ) ) ?) ) ,
187
187
}
188
188
}
189
189
}
190
190
191
+ /// Encrypt a Thrift serializable object
191
192
pub ( crate ) fn encrypt_object < T : TSerializable , W : Write > (
192
- object : T ,
193
- encryptor : & FileEncryptor ,
193
+ object : & T ,
194
+ encryptor : & mut Box < dyn BlockEncryptor > ,
194
195
sink : & mut W ,
195
196
module_aad : & [ u8 ] ,
196
197
) -> Result < ( ) > {
@@ -200,11 +201,46 @@ pub(crate) fn encrypt_object<T: TSerializable, W: Write>(
200
201
object. write_to_out_protocol ( & mut unencrypted_protocol) ?;
201
202
}
202
203
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) ?;
207
205
208
206
sink. write_all ( & encrypted_buffer) ?;
209
207
Ok ( ( ) )
210
208
}
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