1010
1111import org .apache .lucene .backward_codecs .store .EndiannessReverserUtil ;
1212import org .apache .lucene .codecs .CodecUtil ;
13- import org .apache .lucene .store .DataOutput ;
1413import org .apache .lucene .store .Directory ;
1514import org .apache .lucene .store .IOContext ;
1615import org .apache .lucene .store .IndexOutput ;
@@ -204,9 +203,9 @@ public void testFailWhenCannotConsumeSecretStream() throws Exception {
204203 Path configDir = env .configFile ();
205204 try (
206205 Directory directory = newFSDirectory (configDir );
207- IndexOutput indexOutput = directory .createOutput ("elasticsearch.keystore" , IOContext .DEFAULT )
206+ IndexOutput indexOutput = EndiannessReverserUtil .createOutput (directory , "elasticsearch.keystore" , IOContext .DEFAULT )
208207 ) {
209- CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , 3 );
208+ CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , KeyStoreWrapper . V3_VERSION );
210209 indexOutput .writeByte ((byte ) 0 ); // No password
211210 SecureRandom random = Randomness .createSecure ();
212211 byte [] salt = new byte [64 ];
@@ -235,19 +234,19 @@ public void testFailWhenCannotConsumeEncryptedBytesStream() throws Exception {
235234 Path configDir = env .configFile ();
236235 try (
237236 Directory directory = newFSDirectory (configDir );
238- IndexOutput indexOutput = directory .createOutput ("elasticsearch.keystore" , IOContext .DEFAULT )
237+ IndexOutput indexOutput = EndiannessReverserUtil .createOutput (directory , "elasticsearch.keystore" , IOContext .DEFAULT )
239238 ) {
240- CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , 3 );
239+ CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , KeyStoreWrapper . V3_VERSION );
241240 indexOutput .writeByte ((byte ) 0 ); // No password
242241 SecureRandom random = Randomness .createSecure ();
243242 byte [] salt = new byte [64 ];
244243 random .nextBytes (salt );
245244 byte [] iv = new byte [12 ];
246245 random .nextBytes (iv );
246+
247247 ByteArrayOutputStream bytes = new ByteArrayOutputStream ();
248248 CipherOutputStream cipherStream = getCipherStream (bytes , salt , iv );
249249 DataOutputStream output = new DataOutputStream (cipherStream );
250-
251250 possiblyAlterSecretString (output , 0 );
252251 cipherStream .close ();
253252 final byte [] encryptedBytes = bytes .toByteArray ();
@@ -259,17 +258,17 @@ public void testFailWhenCannotConsumeEncryptedBytesStream() throws Exception {
259258 KeyStoreWrapper keystore = KeyStoreWrapper .load (configDir );
260259 SecurityException e = expectThrows (SecurityException .class , () -> keystore .decrypt (new char [0 ]));
261260 assertThat (e .getMessage (), containsString ("Keystore has been corrupted or tampered with" ));
262- assertThat (e .getCause (), instanceOf (EOFException .class ));
261+ assertThat (e .getCause (), instanceOf (ArrayIndexOutOfBoundsException .class ));
263262 }
264263
265264 public void testFailWhenSecretStreamNotConsumed () throws Exception {
266265 assumeFalse ("Cannot open unprotected keystore on FIPS JVM" , inFipsJvm ());
267266 Path configDir = env .configFile ();
268267 try (
269268 Directory directory = newFSDirectory (configDir );
270- IndexOutput indexOutput = directory .createOutput ("elasticsearch.keystore" , IOContext .DEFAULT )
269+ IndexOutput indexOutput = EndiannessReverserUtil .createOutput (directory , "elasticsearch.keystore" , IOContext .DEFAULT )
271270 ) {
272- CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , 3 );
271+ CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , KeyStoreWrapper . V3_VERSION );
273272 indexOutput .writeByte ((byte ) 0 ); // No password
274273 SecureRandom random = Randomness .createSecure ();
275274 byte [] salt = new byte [64 ];
@@ -297,9 +296,9 @@ public void testFailWhenEncryptedBytesStreamIsNotConsumed() throws Exception {
297296 Path configDir = env .configFile ();
298297 try (
299298 Directory directory = newFSDirectory (configDir );
300- IndexOutput indexOutput = directory .createOutput ("elasticsearch.keystore" , IOContext .DEFAULT )
299+ IndexOutput indexOutput = EndiannessReverserUtil .createOutput (directory , "elasticsearch.keystore" , IOContext .DEFAULT )
301300 ) {
302- CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , 3 );
301+ CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , KeyStoreWrapper . V3_VERSION );
303302 indexOutput .writeByte ((byte ) 0 ); // No password
304303 SecureRandom random = Randomness .createSecure ();
305304 byte [] salt = new byte [64 ];
@@ -342,14 +341,8 @@ private void possiblyAlterSecretString(DataOutputStream output, int truncLength)
342341 output .write (secret_value );
343342 }
344343
345- private void possiblyAlterEncryptedBytes (
346- IndexOutput indexOutput ,
347- byte [] salt ,
348- byte [] iv ,
349- byte [] encryptedBytes ,
350- int truncEncryptedDataLength
351- ) throws Exception {
352- DataOutput out = EndiannessReverserUtil .wrapDataOutput (indexOutput );
344+ private void possiblyAlterEncryptedBytes (IndexOutput out , byte [] salt , byte [] iv , byte [] encryptedBytes , int truncEncryptedDataLength )
345+ throws Exception {
353346 out .writeInt (4 + salt .length + 4 + iv .length + 4 + encryptedBytes .length );
354347 out .writeInt (salt .length );
355348 out .writeBytes (salt , salt .length );
@@ -424,7 +417,7 @@ public void testBackcompatV2() throws Exception {
424417 Directory directory = newFSDirectory (configDir );
425418 IndexOutput output = EndiannessReverserUtil .createOutput (directory , "elasticsearch.keystore" , IOContext .DEFAULT );
426419 ) {
427- CodecUtil .writeHeader (output , "elasticsearch.keystore" , 2 );
420+ CodecUtil .writeHeader (output , "elasticsearch.keystore" , KeyStoreWrapper . V2_VERSION );
428421 output .writeByte ((byte ) 0 ); // hasPassword = false
429422 output .writeString ("PKCS12" );
430423 output .writeString ("PBE" ); // string algo
@@ -474,6 +467,42 @@ public void testBackcompatV2() throws Exception {
474467 }
475468 }
476469
470+ public void testBackcompatV4 () throws Exception {
471+ assumeFalse ("Can't run in a FIPS JVM as PBE is not available" , inFipsJvm ());
472+ Path configDir = env .configFile ();
473+ try (
474+ Directory directory = newFSDirectory (configDir );
475+ IndexOutput indexOutput = EndiannessReverserUtil .createOutput (directory , "elasticsearch.keystore" , IOContext .DEFAULT )
476+ ) {
477+ CodecUtil .writeHeader (indexOutput , "elasticsearch.keystore" , KeyStoreWrapper .V4_VERSION );
478+ indexOutput .writeByte ((byte ) 0 ); // No password
479+ SecureRandom random = Randomness .createSecure ();
480+ byte [] salt = new byte [64 ];
481+ random .nextBytes (salt );
482+ byte [] iv = new byte [12 ];
483+ random .nextBytes (iv );
484+ ByteArrayOutputStream bytes = new ByteArrayOutputStream ();
485+ CipherOutputStream cipherStream = getCipherStream (bytes , salt , iv );
486+ DataOutputStream output = new DataOutputStream (cipherStream );
487+ {
488+ byte [] secret_value = "super_secret_value" .getBytes (StandardCharsets .UTF_8 );
489+ output .writeInt (1 ); // One entry
490+ output .writeUTF ("string_setting" );
491+ output .writeInt (secret_value .length );
492+ output .write (secret_value );
493+ }
494+ cipherStream .close ();
495+ final byte [] encryptedBytes = bytes .toByteArray ();
496+ possiblyAlterEncryptedBytes (indexOutput , salt , iv , encryptedBytes , 0 );
497+ CodecUtil .writeFooter (indexOutput );
498+ }
499+
500+ KeyStoreWrapper keystore = KeyStoreWrapper .load (configDir );
501+ keystore .decrypt (new char [0 ]);
502+ SecureString testValue = keystore .getString ("string_setting" );
503+ assertThat (testValue .toString (), equalTo ("super_secret_value" ));
504+ }
505+
477506 public void testStringAndFileDistinction () throws Exception {
478507 final char [] password = getPossibleKeystorePassword ();
479508 final KeyStoreWrapper wrapper = KeyStoreWrapper .create ();
0 commit comments