@@ -2862,28 +2862,42 @@ impl ConfigField for ConfigFileEncryptionProperties {
28622862}
28632863
28642864#[ cfg( feature = "parquet_encryption" ) ]
2865- impl From < ConfigFileEncryptionProperties > for FileEncryptionProperties {
2866- fn from ( val : ConfigFileEncryptionProperties ) -> Self {
2865+ impl TryFrom < ConfigFileEncryptionProperties > for FileEncryptionProperties {
2866+ type Error = DataFusionError ;
2867+
2868+ fn try_from ( val : ConfigFileEncryptionProperties ) -> Result < Self > {
28672869 let mut fep = FileEncryptionProperties :: builder (
2868- hex:: decode ( val. footer_key_as_hex ) . unwrap ( ) ,
2870+ hex:: decode ( val. footer_key_as_hex )
2871+ . map_err ( |e| {
2872+ DataFusionError :: Configuration ( format ! ( "Unable to decode hex footer key from ConfigFileEncryptionProperties: {e}" ) )
2873+ } ) ?,
28692874 )
28702875 . with_plaintext_footer ( !val. encrypt_footer )
28712876 . with_aad_prefix_storage ( val. store_aad_prefix ) ;
28722877
28732878 if !val. footer_key_metadata_as_hex . is_empty ( ) {
28742879 fep = fep. with_footer_key_metadata (
28752880 hex:: decode ( & val. footer_key_metadata_as_hex )
2876- . expect ( "Invalid footer key metadata" ) ,
2881+ . map_err ( |e| {
2882+ DataFusionError :: Configuration ( format ! ( "Unable to decode hex footer key metadata from ConfigFileEncryptionProperties: {e}" ) )
2883+ } ) ?,
28772884 ) ;
28782885 }
28792886
28802887 for ( column_name, encryption_props) in val. column_encryption_properties . iter ( ) {
28812888 let encryption_key = hex:: decode ( & encryption_props. column_key_as_hex )
2882- . expect ( "Invalid column encryption key" ) ;
2889+ . map_err ( |e| {
2890+ DataFusionError :: Configuration ( format ! ( "Unable to decode hex encryption key metadata for column {column_name}: {e}" ) )
2891+ } ) ?;
28832892 let key_metadata = encryption_props
28842893 . column_metadata_as_hex
28852894 . as_ref ( )
2886- . map ( |x| hex:: decode ( x) . expect ( "Invalid column metadata" ) ) ;
2895+ . map ( |x| hex:: decode ( x) )
2896+ . transpose ( )
2897+ . map_err ( |e| {
2898+ DataFusionError :: Configuration ( format ! ( "Unable to decode hex column metadata for column {column_name}: {e}" ) )
2899+ } ) ?;
2900+
28872901 match key_metadata {
28882902 Some ( key_metadata) => {
28892903 fep = fep. with_column_key_and_metadata (
@@ -2899,11 +2913,18 @@ impl From<ConfigFileEncryptionProperties> for FileEncryptionProperties {
28992913 }
29002914
29012915 if !val. aad_prefix_as_hex . is_empty ( ) {
2902- let aad_prefix: Vec < u8 > =
2903- hex:: decode ( & val. aad_prefix_as_hex ) . expect ( "Invalid AAD prefix" ) ;
2916+ let aad_prefix: Vec < u8 > = hex:: decode ( & val. aad_prefix_as_hex ) . map_err ( |e| {
2917+ DataFusionError :: Configuration ( format ! (
2918+ "Unable to decode hex AAD prefix from ConfigFileEncryptionProperties: {e}"
2919+ ) )
2920+ } ) ?;
29042921 fep = fep. with_aad_prefix ( aad_prefix) ;
29052922 }
2906- Arc :: unwrap_or_clone ( fep. build ( ) . unwrap ( ) )
2923+ Ok ( Arc :: unwrap_or_clone ( fep. build ( ) . map_err ( |e| {
2924+ DataFusionError :: Configuration ( format ! (
2925+ "Could not build FileEncryptionProperties: {e}"
2926+ ) )
2927+ } ) ?) )
29072928 }
29082929}
29092930
@@ -3019,36 +3040,54 @@ impl ConfigField for ConfigFileDecryptionProperties {
30193040}
30203041
30213042#[ cfg( feature = "parquet_encryption" ) ]
3022- impl From < ConfigFileDecryptionProperties > for FileDecryptionProperties {
3023- fn from ( val : ConfigFileDecryptionProperties ) -> Self {
3043+ impl TryFrom < ConfigFileDecryptionProperties > for FileDecryptionProperties {
3044+ type Error = DataFusionError ;
3045+
3046+ fn try_from ( val : ConfigFileDecryptionProperties ) -> Result < Self > {
30243047 let mut column_names: Vec < & str > = Vec :: new ( ) ;
30253048 let mut column_keys: Vec < Vec < u8 > > = Vec :: new ( ) ;
30263049
30273050 for ( col_name, decryption_properties) in val. column_decryption_properties . iter ( ) {
3051+ let column_key_as_hex = hex:: decode ( & decryption_properties. column_key_as_hex ) . map_err ( |e| {
3052+ DataFusionError :: Configuration ( format !
3053+ ( "Could not decode hex column key from ConfigFileDecryptionProperties for column name {col_name}: {e}." ) )
3054+ } ) ?;
30283055 column_names. push ( col_name. as_str ( ) ) ;
3029- column_keys. push (
3030- hex:: decode ( & decryption_properties. column_key_as_hex )
3031- . expect ( "Invalid column decryption key" ) ,
3032- ) ;
3056+ column_keys. push ( column_key_as_hex) ;
30333057 }
30343058
3035- let mut fep = FileDecryptionProperties :: builder (
3036- hex:: decode ( val. footer_key_as_hex ) . expect ( "Invalid footer key" ) ,
3037- )
3038- . with_column_keys ( column_names, column_keys)
3039- . unwrap ( ) ;
3059+ let footer_key = hex:: decode ( val. footer_key_as_hex ) . map_err ( |e| {
3060+ DataFusionError :: Configuration ( format ! (
3061+ "Could not decode hex footer key from ConfigFileDecryptionProperties: {e}."
3062+ ) )
3063+ } ) ?;
3064+
3065+ let mut fep = FileDecryptionProperties :: builder ( footer_key)
3066+ . with_column_keys ( column_names, column_keys)
3067+ . map_err ( |e| {
3068+ DataFusionError :: Configuration ( format ! (
3069+ "Could not set column keys on FileDecryptionPropertiesBuilder: {e}."
3070+ ) )
3071+ } ) ?;
30403072
30413073 if !val. footer_signature_verification {
30423074 fep = fep. disable_footer_signature_verification ( ) ;
30433075 }
30443076
30453077 if !val. aad_prefix_as_hex . is_empty ( ) {
3046- let aad_prefix =
3047- hex:: decode ( & val. aad_prefix_as_hex ) . expect ( "Invalid AAD prefix" ) ;
3078+ let aad_prefix = hex:: decode ( & val. aad_prefix_as_hex ) . map_err ( |e| {
3079+ DataFusionError :: Configuration ( format ! (
3080+ "Could not decode hex AAD prefix from ConfigFileDecryptionProperties: {e}."
3081+ ) )
3082+ } ) ?;
30483083 fep = fep. with_aad_prefix ( aad_prefix) ;
30493084 }
30503085
3051- Arc :: unwrap_or_clone ( fep. build ( ) . unwrap ( ) )
3086+ Ok ( Arc :: unwrap_or_clone ( fep. build ( ) . map_err ( |e| {
3087+ DataFusionError :: Configuration ( format ! (
3088+ "Could not build FileDecryptionProperties: {e}."
3089+ ) )
3090+ } ) ?) )
30523091 }
30533092}
30543093
@@ -3586,13 +3625,13 @@ mod tests {
35863625 let config_encrypt =
35873626 ConfigFileEncryptionProperties :: from ( & file_encryption_properties) ;
35883627 let encryption_properties_built =
3589- Arc :: new ( FileEncryptionProperties :: from ( config_encrypt. clone ( ) ) ) ;
3628+ Arc :: new ( FileEncryptionProperties :: try_from ( config_encrypt. clone ( ) ) . unwrap ( ) ) ;
35903629 assert_eq ! ( file_encryption_properties, encryption_properties_built) ;
35913630
35923631 let config_decrypt =
35933632 ConfigFileDecryptionProperties :: try_from ( & decryption_properties) . unwrap ( ) ;
35943633 let decryption_properties_built =
3595- Arc :: new ( FileDecryptionProperties :: from ( config_decrypt. clone ( ) ) ) ;
3634+ Arc :: new ( FileDecryptionProperties :: try_from ( config_decrypt. clone ( ) ) . unwrap ( ) ) ;
35963635 assert_eq ! ( decryption_properties, decryption_properties_built) ;
35973636
35983637 ///////////////////////////////////////////////////////////////////////////////////
@@ -3678,6 +3717,112 @@ mod tests {
36783717 ) ;
36793718 }
36803719
3720+ #[ cfg( feature = "parquet_encryption" ) ]
3721+ #[ test]
3722+ fn parquet_encryption_invalid_hex_errors_encryption ( ) {
3723+ use crate :: config:: ColumnEncryptionProperties ;
3724+ use crate :: config:: ConfigFileEncryptionProperties ;
3725+ use parquet:: encryption:: encrypt:: FileEncryptionProperties ;
3726+
3727+ // Encryption: invalid footer key hex
3728+ let mut enc = ConfigFileEncryptionProperties :: default ( ) ;
3729+ enc. footer_key_as_hex = "not_hex" . to_string ( ) ;
3730+ let err = FileEncryptionProperties :: try_from ( enc)
3731+ . unwrap_err ( )
3732+ . to_string ( ) ;
3733+ assert ! ( err. contains( "Unable to decode hex footer key" ) ) ;
3734+
3735+ // Encryption: invalid footer key metadata hex
3736+ let mut enc = ConfigFileEncryptionProperties :: default ( ) ;
3737+ enc. footer_key_as_hex = hex:: encode ( b"0123456789012345" ) ;
3738+ enc. footer_key_metadata_as_hex = "zz" . to_string ( ) ;
3739+ let err = FileEncryptionProperties :: try_from ( enc)
3740+ . unwrap_err ( )
3741+ . to_string ( ) ;
3742+ assert ! ( err. contains( "Unable to decode hex footer key metadata" ) ) ;
3743+
3744+ // Encryption: invalid column key hex
3745+ let mut enc = ConfigFileEncryptionProperties :: default ( ) ;
3746+ enc. footer_key_as_hex = hex:: encode ( b"0123456789012345" ) ;
3747+ enc. column_encryption_properties . insert (
3748+ "col1" . to_string ( ) ,
3749+ ColumnEncryptionProperties {
3750+ column_key_as_hex : "bad" . to_string ( ) ,
3751+ column_metadata_as_hex : None ,
3752+ } ,
3753+ ) ;
3754+ let err = FileEncryptionProperties :: try_from ( enc)
3755+ . unwrap_err ( )
3756+ . to_string ( ) ;
3757+ assert ! (
3758+ err. contains( "Unable to decode hex encryption key metadata for column col1" )
3759+ ) ;
3760+
3761+ // Encryption: invalid column metadata hex
3762+ let mut enc = ConfigFileEncryptionProperties :: default ( ) ;
3763+ enc. footer_key_as_hex = hex:: encode ( b"0123456789012345" ) ;
3764+ enc. column_encryption_properties . insert (
3765+ "col1" . to_string ( ) ,
3766+ ColumnEncryptionProperties {
3767+ column_key_as_hex : hex:: encode ( b"1234567890123450" ) ,
3768+ column_metadata_as_hex : Some ( "zz" . to_string ( ) ) ,
3769+ } ,
3770+ ) ;
3771+ let err = FileEncryptionProperties :: try_from ( enc)
3772+ . unwrap_err ( )
3773+ . to_string ( ) ;
3774+ assert ! ( err. contains( "Unable to decode hex column metadata for column col1" ) ) ;
3775+
3776+ // Encryption: invalid AAD prefix hex
3777+ let mut enc = ConfigFileEncryptionProperties :: default ( ) ;
3778+ enc. footer_key_as_hex = hex:: encode ( b"0123456789012345" ) ;
3779+ enc. aad_prefix_as_hex = "zz" . to_string ( ) ;
3780+ let err = FileEncryptionProperties :: try_from ( enc)
3781+ . unwrap_err ( )
3782+ . to_string ( ) ;
3783+ assert ! ( err. contains( "Unable to decode hex AAD prefix" ) ) ;
3784+ }
3785+
3786+ #[ cfg( feature = "parquet_encryption" ) ]
3787+ #[ test]
3788+ fn parquet_encryption_invalid_hex_errors_decryption ( ) {
3789+ use crate :: config:: ColumnDecryptionProperties ;
3790+ use crate :: config:: ConfigFileDecryptionProperties ;
3791+ use parquet:: encryption:: decrypt:: FileDecryptionProperties ;
3792+
3793+ // Decryption: invalid column key hex
3794+ let mut dec = ConfigFileDecryptionProperties :: default ( ) ;
3795+ dec. footer_key_as_hex = hex:: encode ( b"0123456789012345" ) ;
3796+ dec. column_decryption_properties . insert (
3797+ "col1" . to_string ( ) ,
3798+ ColumnDecryptionProperties {
3799+ column_key_as_hex : "bad" . to_string ( ) ,
3800+ } ,
3801+ ) ;
3802+ let err = FileDecryptionProperties :: try_from ( dec)
3803+ . unwrap_err ( )
3804+ . to_string ( ) ;
3805+ assert ! ( err. contains( "Could not decode hex column key" ) ) ;
3806+ assert ! ( err. contains( "col1" ) ) ;
3807+
3808+ // Decryption: invalid footer key hex
3809+ let mut dec = ConfigFileDecryptionProperties :: default ( ) ;
3810+ dec. footer_key_as_hex = "bad" . to_string ( ) ;
3811+ let err = FileDecryptionProperties :: try_from ( dec)
3812+ . unwrap_err ( )
3813+ . to_string ( ) ;
3814+ assert ! ( err. contains( "Could not decode hex footer key" ) ) ;
3815+
3816+ // Decryption: invalid AAD prefix hex
3817+ let mut dec = ConfigFileDecryptionProperties :: default ( ) ;
3818+ dec. footer_key_as_hex = hex:: encode ( b"0123456789012345" ) ;
3819+ dec. aad_prefix_as_hex = "zz" . to_string ( ) ;
3820+ let err = FileDecryptionProperties :: try_from ( dec)
3821+ . unwrap_err ( )
3822+ . to_string ( ) ;
3823+ assert ! ( err. contains( "Could not decode hex AAD prefix" ) ) ;
3824+ }
3825+
36813826 #[ cfg( feature = "parquet_encryption" ) ]
36823827 #[ test]
36833828 fn parquet_encryption_factory_config ( ) {
0 commit comments