6868import java .nio .file .Path ;
6969import java .security .GeneralSecurityException ;
7070import java .security .KeyStore ;
71+ import java .security .KeyStoreException ;
7172import java .security .MessageDigest ;
73+ import java .security .NoSuchAlgorithmException ;
74+ import java .security .NoSuchProviderException ;
7275import java .security .SecureRandom ;
76+ import java .security .cert .CertificateException ;
77+ import java .security .spec .InvalidKeySpecException ;
7378import java .util .ArrayList ;
7479import java .util .Arrays ;
7580import java .util .Base64 ;
@@ -366,29 +371,8 @@ public void testIllegalSettingName() throws Exception {
366371
367372 public void testBackcompatV1 () throws Exception {
368373 assumeFalse ("Can't run in a FIPS JVM as PBE is not available" , inFipsJvm ());
374+ generateV1 ();
369375 Path configDir = env .configDir ();
370- NIOFSDirectory directory = new NIOFSDirectory (configDir );
371- try (IndexOutput output = EndiannessReverserUtil .createOutput (directory , "opensearch.keystore" , IOContext .DEFAULT )) {
372- CodecUtil .writeHeader (output , "opensearch.keystore" , 1 );
373- output .writeByte ((byte ) 0 ); // hasPassword = false
374- output .writeString ("PKCS12" );
375- output .writeString ("PBE" );
376-
377- SecretKeyFactory secretFactory = SecretKeyFactory .getInstance ("PBE" );
378- KeyStore keystore = KeyStore .getInstance ("PKCS12" );
379- keystore .load (null , null );
380- SecretKey secretKey = secretFactory .generateSecret (new PBEKeySpec ("stringSecretValue" .toCharArray ()));
381- KeyStore .ProtectionParameter protectionParameter = new KeyStore .PasswordProtection (new char [0 ]);
382- keystore .setEntry ("string_setting" , new KeyStore .SecretKeyEntry (secretKey ), protectionParameter );
383-
384- ByteArrayOutputStream keystoreBytesStream = new ByteArrayOutputStream ();
385- keystore .store (keystoreBytesStream , new char [0 ]);
386- byte [] keystoreBytes = keystoreBytesStream .toByteArray ();
387- output .writeInt (keystoreBytes .length );
388- output .writeBytes (keystoreBytes , keystoreBytes .length );
389- CodecUtil .writeFooter (output );
390- }
391-
392376 KeyStoreWrapper keystore = KeyStoreWrapper .load (configDir );
393377 keystore .decrypt (new char [0 ]);
394378 SecureString testValue = keystore .getString ("string_setting" );
@@ -397,47 +381,8 @@ public void testBackcompatV1() throws Exception {
397381
398382 public void testBackcompatV2 () throws Exception {
399383 assumeFalse ("Can't run in a FIPS JVM as PBE is not available" , inFipsJvm ());
384+ byte [] fileBytes = generateV2 ();
400385 Path configDir = env .configDir ();
401- NIOFSDirectory directory = new NIOFSDirectory (configDir );
402- byte [] fileBytes = new byte [20 ];
403- random ().nextBytes (fileBytes );
404- try (IndexOutput output = EndiannessReverserUtil .createOutput (directory , "opensearch.keystore" , IOContext .DEFAULT )) {
405-
406- CodecUtil .writeHeader (output , "opensearch.keystore" , 2 );
407- output .writeByte ((byte ) 0 ); // hasPassword = false
408- output .writeString ("PKCS12" );
409- output .writeString ("PBE" ); // string algo
410- output .writeString ("PBE" ); // file algo
411-
412- output .writeVInt (2 ); // num settings
413- output .writeString ("string_setting" );
414- output .writeString ("STRING" );
415- output .writeString ("file_setting" );
416- output .writeString ("FILE" );
417-
418- SecretKeyFactory secretFactory = SecretKeyFactory .getInstance ("PBE" );
419- KeyStore keystore = KeyStore .getInstance ("PKCS12" );
420- keystore .load (null , null );
421- SecretKey secretKey = secretFactory .generateSecret (new PBEKeySpec ("stringSecretValue" .toCharArray ()));
422- KeyStore .ProtectionParameter protectionParameter = new KeyStore .PasswordProtection (new char [0 ]);
423- keystore .setEntry ("string_setting" , new KeyStore .SecretKeyEntry (secretKey ), protectionParameter );
424-
425- byte [] base64Bytes = Base64 .getEncoder ().encode (fileBytes );
426- char [] chars = new char [base64Bytes .length ];
427- for (int i = 0 ; i < chars .length ; ++i ) {
428- chars [i ] = (char ) base64Bytes [i ]; // PBE only stores the lower 8 bits, so this narrowing is ok
429- }
430- secretKey = secretFactory .generateSecret (new PBEKeySpec (chars ));
431- keystore .setEntry ("file_setting" , new KeyStore .SecretKeyEntry (secretKey ), protectionParameter );
432-
433- ByteArrayOutputStream keystoreBytesStream = new ByteArrayOutputStream ();
434- keystore .store (keystoreBytesStream , new char [0 ]);
435- byte [] keystoreBytes = keystoreBytesStream .toByteArray ();
436- output .writeInt (keystoreBytes .length );
437- output .writeBytes (keystoreBytes , keystoreBytes .length );
438- CodecUtil .writeFooter (output );
439- }
440-
441386 KeyStoreWrapper keystore = KeyStoreWrapper .load (configDir );
442387 keystore .decrypt (new char [0 ]);
443388 SecureString testValue = keystore .getString ("string_setting" );
@@ -497,6 +442,77 @@ public void testLegacyV3() throws GeneralSecurityException, IOException {
497442 assertThat (toByteArray (wrapper .getFile ("file_setting" )), equalTo ("file_value" .getBytes (StandardCharsets .UTF_8 )));
498443 }
499444
445+ private void generateV1 () throws IOException , NoSuchAlgorithmException , NoSuchProviderException , CertificateException ,
446+ InvalidKeySpecException , KeyStoreException {
447+ Path configDir = env .configDir ();
448+ NIOFSDirectory directory = new NIOFSDirectory (configDir );
449+ try (IndexOutput output = EndiannessReverserUtil .createOutput (directory , "opensearch.keystore" , IOContext .DEFAULT )) {
450+ CodecUtil .writeHeader (output , "opensearch.keystore" , 1 );
451+ output .writeByte ((byte ) 0 ); // hasPassword = false
452+ output .writeString ("PKCS12" );
453+ output .writeString ("PBE" );
454+
455+ SecretKeyFactory secretFactory = SecretKeyFactory .getInstance ("PBE" , "SunJCE" );
456+ KeyStore keystore = KeyStore .getInstance ("PKCS12" , "SUN" );
457+ keystore .load (null , null );
458+ SecretKey secretKey = secretFactory .generateSecret (new PBEKeySpec ("stringSecretValue" .toCharArray ()));
459+ KeyStore .ProtectionParameter protectionParameter = new KeyStore .PasswordProtection (new char [0 ]);
460+ keystore .setEntry ("string_setting" , new KeyStore .SecretKeyEntry (secretKey ), protectionParameter );
461+
462+ ByteArrayOutputStream keystoreBytesStream = new ByteArrayOutputStream ();
463+ keystore .store (keystoreBytesStream , new char [0 ]);
464+ byte [] keystoreBytes = keystoreBytesStream .toByteArray ();
465+ output .writeInt (keystoreBytes .length );
466+ output .writeBytes (keystoreBytes , keystoreBytes .length );
467+ CodecUtil .writeFooter (output );
468+ }
469+ }
470+
471+ private byte [] generateV2 () throws Exception {
472+ Path configDir = env .configDir ();
473+ NIOFSDirectory directory = new NIOFSDirectory (configDir );
474+ byte [] fileBytes = new byte [20 ];
475+ random ().nextBytes (fileBytes );
476+ try (IndexOutput output = EndiannessReverserUtil .createOutput (directory , "opensearch.keystore" , IOContext .DEFAULT )) {
477+
478+ CodecUtil .writeHeader (output , "opensearch.keystore" , 2 );
479+ output .writeByte ((byte ) 0 ); // hasPassword = false
480+ output .writeString ("PKCS12" );
481+ output .writeString ("PBE" ); // string algo
482+ output .writeString ("PBE" ); // file algo
483+
484+ output .writeVInt (2 ); // num settings
485+ output .writeString ("string_setting" );
486+ output .writeString ("STRING" );
487+ output .writeString ("file_setting" );
488+ output .writeString ("FILE" );
489+
490+ SecretKeyFactory secretFactory = SecretKeyFactory .getInstance ("PBE" , "SunJCE" );
491+ KeyStore keystore = KeyStore .getInstance ("PKCS12" , "SUN" );
492+ keystore .load (null , null );
493+ SecretKey secretKey = secretFactory .generateSecret (new PBEKeySpec ("stringSecretValue" .toCharArray ()));
494+ KeyStore .ProtectionParameter protectionParameter = new KeyStore .PasswordProtection (new char [0 ]);
495+ keystore .setEntry ("string_setting" , new KeyStore .SecretKeyEntry (secretKey ), protectionParameter );
496+
497+ byte [] base64Bytes = Base64 .getEncoder ().encode (fileBytes );
498+ char [] chars = new char [base64Bytes .length ];
499+ for (int i = 0 ; i < chars .length ; ++i ) {
500+ chars [i ] = (char ) base64Bytes [i ]; // PBE only stores the lower 8 bits, so this narrowing is ok
501+ }
502+ secretKey = secretFactory .generateSecret (new PBEKeySpec (chars ));
503+ keystore .setEntry ("file_setting" , new KeyStore .SecretKeyEntry (secretKey ), protectionParameter );
504+
505+ ByteArrayOutputStream keystoreBytesStream = new ByteArrayOutputStream ();
506+ keystore .store (keystoreBytesStream , new char [0 ]);
507+ byte [] keystoreBytes = keystoreBytesStream .toByteArray ();
508+ output .writeInt (keystoreBytes .length );
509+ output .writeBytes (keystoreBytes , keystoreBytes .length );
510+ CodecUtil .writeFooter (output );
511+ }
512+
513+ return fileBytes ;
514+ }
515+
500516 private byte [] toByteArray (final InputStream is ) throws IOException {
501517 final ByteArrayOutputStream os = new ByteArrayOutputStream ();
502518 final byte [] buffer = new byte [1024 ];
0 commit comments