@@ -13,7 +13,7 @@ class FieldLevelEncryption
1313 #
1414 # Create a new instance with the provided configuration
1515 #
16- # @param [Object ] config Configuration object
16+ # @param [Hash ] config Configuration object
1717 #
1818 def initialize ( config )
1919 @config = config
@@ -27,7 +27,7 @@ def initialize(config)
2727 # Encrypt parts of a HTTP request using the given config
2828 #
2929 # @param [String] endpoint HTTP URL for the current call
30- # @param [Object] header HTTP header
30+ # @param [Object|nil ] header HTTP header
3131 # @param [String,Hash] body HTTP body
3232 #
3333 # @return [Hash] Hash with two keys:
@@ -37,19 +37,20 @@ def initialize(config)
3737 def encrypt ( endpoint , header , body )
3838 body = JSON . parse ( body ) if body . is_a? ( String )
3939 config = config? ( endpoint )
40+ body_map = body
4041 if config
4142 if !@is_with_header
42- config [ 'toEncrypt' ] . each do |v |
43+ body_map = config [ 'toEncrypt' ] . map do |v |
4344 encrypt_with_body ( v , body )
4445 end
4546 else
4647 enc_params = @crypto . new_encryption_params
47- config [ 'toEncrypt' ] . each do |v |
48+ body_map = config [ 'toEncrypt' ] . map do |v |
4849 body = encrypt_with_header ( v , enc_params , header , body )
4950 end
5051 end
5152 end
52- { header : header , body : body . json }
53+ { header : header , body : config ? compute_body ( config [ 'toEncrypt' ] , body_map ) { body . json } : body . json }
5354 end
5455
5556 #
@@ -62,9 +63,10 @@ def encrypt(endpoint, header, body)
6263 def decrypt ( response )
6364 response = JSON . parse ( response )
6465 config = config? ( response [ 'request' ] [ 'url' ] )
66+ body_map = response
6567 if config
6668 if !@is_with_header
67- config [ 'toDecrypt' ] . each do |v |
69+ body_map = config [ 'toDecrypt' ] . map do |v |
6870 decrypt_with_body ( v , response [ 'body' ] )
6971 end
7072 else
@@ -74,6 +76,7 @@ def decrypt(response)
7476 end
7577 end
7678 end
79+ response [ 'body' ] = compute_body ( config [ 'toDecrypt' ] , body_map ) { response [ 'body' ] } unless config . nil?
7780 JSON . generate ( response )
7881 end
7982
@@ -82,14 +85,19 @@ def decrypt(response)
8285 def encrypt_with_body ( path , body )
8386 elem = elem_from_path ( path [ 'element' ] , body )
8487 return unless elem && elem [ :node ]
88+
8589 encrypted_data = @crypto . encrypt_data ( data : JSON . generate ( elem [ :node ] ) )
86- McAPI ::Utils . mutate_obj_prop ( path [ 'obj' ] , encrypted_data , body )
87- McAPI ::Utils . delete_node ( path [ 'element' ] , body ) if path [ 'element' ] != "#{ path [ 'obj' ] } .#{ @config [ 'encryptedValueFieldName' ] } "
90+ body = McAPI ::Utils . mutate_obj_prop ( path [ 'obj' ] , encrypted_data , body )
91+ unless json_root? ( path [ 'obj' ] ) || path [ 'element' ] == "#{ path [ 'obj' ] } .#{ @config [ 'encryptedValueFieldName' ] } "
92+ McAPI ::Utils . delete_node ( path [ 'element' ] , body )
93+ end
94+ body
8895 end
8996
9097 def encrypt_with_header ( path , enc_params , header , body )
9198 elem = elem_from_path ( path [ 'element' ] , body )
9299 return unless elem && elem [ :node ]
100+
93101 encrypted_data = @crypto . encrypt_data ( data : JSON . generate ( elem [ :node ] ) , encryption_params : enc_params )
94102 body = { path [ 'obj' ] => { @config [ 'encryptedValueFieldName' ] => encrypted_data [ @config [ 'encryptedValueFieldName' ] ] } }
95103 set_header ( header , enc_params )
@@ -99,9 +107,11 @@ def encrypt_with_header(path, enc_params, header, body)
99107 def decrypt_with_body ( path , body )
100108 elem = elem_from_path ( path [ 'element' ] , body )
101109 return unless elem && elem [ :node ]
110+
102111 decrypted = @crypto . decrypt_data ( elem [ :node ] [ @config [ 'encryptedValueFieldName' ] ] ,
103- elem [ :node ] [ @config [ 'ivFieldName' ] ] ,
104- elem [ :node ] [ @config [ 'encryptedKeyFieldName' ] ] )
112+ elem [ :node ] [ @config [ 'ivFieldName' ] ] ,
113+ elem [ :node ] [ @config [ 'encryptedKeyFieldName' ] ] ,
114+ elem [ :node ] [ @config [ 'oaepHashingAlgorithmFieldName' ] ] )
105115 begin
106116 decrypted = JSON . parse ( decrypted )
107117 rescue JSON ::ParserError
@@ -116,7 +126,8 @@ def decrypt_with_header(path, elem, response)
116126 response [ 'body' ] . clear
117127 response [ 'body' ] = JSON . parse ( @crypto . decrypt_data ( encrypted_data ,
118128 response [ 'headers' ] [ @config [ 'ivHeaderName' ] ] [ 0 ] ,
119- response [ 'headers' ] [ @config [ 'encryptedKeyHeaderName' ] ] [ 0 ] ) )
129+ response [ 'headers' ] [ @config [ 'encryptedKeyHeaderName' ] ] [ 0 ] ,
130+ response [ 'headers' ] [ @config [ 'oaepHashingAlgorithmHeaderName' ] ] [ 0 ] ) )
120131 end
121132
122133 def elem_from_path ( path , obj )
@@ -125,7 +136,7 @@ def elem_from_path(path, obj)
125136 if path && !paths . empty?
126137 paths . each do |e |
127138 parent = obj
128- obj = obj [ e ]
139+ obj = json_root? ( e ) ? obj : obj [ e ]
129140 end
130141 end
131142 { node : obj , parent : parent }
@@ -147,6 +158,18 @@ def set_header(header, params)
147158 header [ @config [ 'oaepHashingAlgorithmHeaderName' ] ] = params [ :oaepHashingAlgorithm ] . sub ( '-' , '' )
148159 header [ @config [ 'publicKeyFingerprintHeaderName' ] ] = params [ :publicKeyFingerprint ]
149160 end
161+
162+ def json_root? ( elem )
163+ elem == '$'
164+ end
165+
166+ def compute_body ( config_param , body_map )
167+ encryption_param? ( config_param , body_map ) ? body_map [ 0 ] : yield
168+ end
169+
170+ def encryption_param? ( enc_param , body_map )
171+ enc_param . length == 1 && body_map . length == 1
172+ end
150173 end
151174 end
152175end
0 commit comments