Skip to content

Commit 1ce524f

Browse files
authored
Revert "Increase KDF iteration count in KeyStoreWrapper (#107107)"
This reverts commit 8830637.
1 parent bdc9873 commit 1ce524f

File tree

5 files changed

+12
-60
lines changed

5 files changed

+12
-60
lines changed

distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/KeyStoreWrapperTests.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -457,26 +457,6 @@ public void testLegacyV3() throws GeneralSecurityException, IOException {
457457
assertThat(toByteArray(wrapper.getFile("file_setting")), equalTo("file_value".getBytes(StandardCharsets.UTF_8)));
458458
}
459459

460-
public void testLegacyV5() throws GeneralSecurityException, IOException {
461-
final Path configDir = createTempDir();
462-
final Path keystore = configDir.resolve("elasticsearch.keystore");
463-
try (
464-
InputStream is = KeyStoreWrapperTests.class.getResourceAsStream("/format-v5-with-password-elasticsearch.keystore");
465-
OutputStream os = Files.newOutputStream(keystore)
466-
) {
467-
final byte[] buffer = new byte[4096];
468-
int readBytes;
469-
while ((readBytes = is.read(buffer)) > 0) {
470-
os.write(buffer, 0, readBytes);
471-
}
472-
}
473-
final KeyStoreWrapper wrapper = KeyStoreWrapper.load(configDir);
474-
assertNotNull(wrapper);
475-
wrapper.decrypt("keystorepassword".toCharArray());
476-
assertThat(wrapper.getFormatVersion(), equalTo(5));
477-
assertThat(wrapper.getSettingNames(), equalTo(Set.of("keystore.seed")));
478-
}
479-
480460
public void testSerializationNewlyCreated() throws Exception {
481461
final KeyStoreWrapper wrapper = KeyStoreWrapper.create();
482462
wrapper.setString("string_setting", "string_value".toCharArray());

distribution/tools/keystore-cli/src/test/java/org/elasticsearch/cli/keystore/UpgradeKeyStoreCommandTests.java

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.elasticsearch.cli.ProcessInfo;
1515
import org.elasticsearch.cli.UserException;
1616
import org.elasticsearch.common.settings.KeyStoreWrapper;
17-
import org.elasticsearch.core.Nullable;
1817
import org.elasticsearch.env.Environment;
1918

2019
import java.io.InputStream;
@@ -47,20 +46,8 @@ public void testKeystoreUpgradeV4() throws Exception {
4746
assertKeystoreUpgrade("/format-v4-elasticsearch.keystore", KeyStoreWrapper.V4_VERSION);
4847
}
4948

50-
public void testKeystoreUpgradeV5() throws Exception {
51-
assertKeystoreUpgradeWithPassword("/format-v5-with-password-elasticsearch.keystore", KeyStoreWrapper.LE_VERSION);
52-
}
53-
5449
private void assertKeystoreUpgrade(String file, int version) throws Exception {
5550
assumeFalse("Cannot open unprotected keystore on FIPS JVM", inFipsJvm());
56-
assertKeystoreUpgrade(file, version, null);
57-
}
58-
59-
private void assertKeystoreUpgradeWithPassword(String file, int version) throws Exception {
60-
assertKeystoreUpgrade(file, version, "keystorepassword");
61-
}
62-
63-
private void assertKeystoreUpgrade(String file, int version, @Nullable String password) throws Exception {
6451
final Path keystore = KeyStoreWrapper.keystorePath(env.configFile());
6552
try (InputStream is = KeyStoreWrapperTests.class.getResourceAsStream(file); OutputStream os = Files.newOutputStream(keystore)) {
6653
is.transferTo(os);
@@ -69,17 +56,11 @@ private void assertKeystoreUpgrade(String file, int version, @Nullable String pa
6956
assertNotNull(beforeUpgrade);
7057
assertThat(beforeUpgrade.getFormatVersion(), equalTo(version));
7158
}
72-
if (password != null) {
73-
terminal.addSecretInput(password);
74-
terminal.addSecretInput(password);
75-
}
7659
execute();
77-
terminal.reset();
78-
7960
try (KeyStoreWrapper afterUpgrade = KeyStoreWrapper.load(env.configFile())) {
8061
assertNotNull(afterUpgrade);
8162
assertThat(afterUpgrade.getFormatVersion(), equalTo(KeyStoreWrapper.CURRENT_VERSION));
82-
afterUpgrade.decrypt(password != null ? password.toCharArray() : new char[0]);
63+
afterUpgrade.decrypt(new char[0]);
8364
assertThat(afterUpgrade.getSettingNames(), hasItem(KeyStoreWrapper.SEED_SETTING.getKey()));
8465
}
8566
}
@@ -88,4 +69,5 @@ public void testKeystoreDoesNotExist() {
8869
final UserException e = expectThrows(UserException.class, this::execute);
8970
assertThat(e, hasToString(containsString("keystore not found at [" + KeyStoreWrapper.keystorePath(env.configFile()) + "]")));
9071
}
72+
9173
}

docs/changelog/107107.yaml

Lines changed: 0 additions & 5 deletions
This file was deleted.

server/src/main/java/org/elasticsearch/common/settings/KeyStoreWrapper.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,19 @@ public void writeTo(StreamOutput out) throws IOException {
114114

115115
/** The oldest metadata format version that can be read. */
116116
private static final int MIN_FORMAT_VERSION = 3;
117+
/** Legacy versions of the metadata written before the keystore data. */
118+
public static final int V2_VERSION = 2;
117119
public static final int V3_VERSION = 3;
118120
public static final int V4_VERSION = 4;
119121
/** The version where lucene directory API changed from BE to LE. */
120122
public static final int LE_VERSION = 5;
121-
public static final int HIGHER_KDF_ITERATION_COUNT_VERSION = 6;
122-
public static final int CURRENT_VERSION = HIGHER_KDF_ITERATION_COUNT_VERSION;
123+
public static final int CURRENT_VERSION = LE_VERSION;
123124

124125
/** The algorithm used to derive the cipher key from a password. */
125126
private static final String KDF_ALGO = "PBKDF2WithHmacSHA512";
126127

127128
/** The number of iterations to derive the cipher key. */
128-
private static final int KDF_ITERS = 210000;
129+
private static final int KDF_ITERS = 10000;
129130

130131
/**
131132
* The number of bits for the cipher key.
@@ -154,7 +155,6 @@ public void writeTo(StreamOutput out) throws IOException {
154155
// 3: FIPS compliant algos, ES 6.3
155156
// 4: remove distinction between string/files, ES 6.8/7.1
156157
// 5: Lucene directory API changed to LE, ES 8.0
157-
// 6: increase KDF iteration count, ES 8.14
158158

159159
/** The metadata format version used to read the current keystore wrapper. */
160160
private final int formatVersion;
@@ -317,8 +317,8 @@ public boolean hasPassword() {
317317
return hasPassword;
318318
}
319319

320-
private static Cipher createCipher(int opmode, char[] password, byte[] salt, byte[] iv, int kdfIters) throws GeneralSecurityException {
321-
PBEKeySpec keySpec = new PBEKeySpec(password, salt, kdfIters, CIPHER_KEY_BITS);
320+
private static Cipher createCipher(int opmode, char[] password, byte[] salt, byte[] iv) throws GeneralSecurityException {
321+
PBEKeySpec keySpec = new PBEKeySpec(password, salt, KDF_ITERS, CIPHER_KEY_BITS);
322322
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KDF_ALGO);
323323
SecretKey secretKey;
324324
try {
@@ -337,11 +337,6 @@ private static Cipher createCipher(int opmode, char[] password, byte[] salt, byt
337337
return cipher;
338338
}
339339

340-
private static int getKdfIterationCountForVersion(int formatVersion) {
341-
// iteration count was increased in version 6; it was 10,000 in previous versions
342-
return formatVersion < HIGHER_KDF_ITERATION_COUNT_VERSION ? 10000 : KDF_ITERS;
343-
}
344-
345340
/**
346341
* Decrypts the underlying keystore data.
347342
*
@@ -370,7 +365,7 @@ public void decrypt(char[] password) throws GeneralSecurityException, IOExceptio
370365
throw new SecurityException("Keystore has been corrupted or tampered with", e);
371366
}
372367

373-
Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, salt, iv, getKdfIterationCountForVersion(formatVersion));
368+
Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, salt, iv);
374369
try (
375370
ByteArrayInputStream bytesStream = new ByteArrayInputStream(encryptedBytes);
376371
CipherInputStream cipherStream = new CipherInputStream(bytesStream, cipher);
@@ -408,11 +403,11 @@ private static byte[] readByteArray(DataInput input) throws IOException {
408403
}
409404

410405
/** Encrypt the keystore entries and return the encrypted data. */
411-
private byte[] encrypt(char[] password, byte[] salt, byte[] iv, int kdfIterationCount) throws GeneralSecurityException, IOException {
406+
private byte[] encrypt(char[] password, byte[] salt, byte[] iv) throws GeneralSecurityException, IOException {
412407
assert isLoaded();
413408

414409
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
415-
Cipher cipher = createCipher(Cipher.ENCRYPT_MODE, password, salt, iv, kdfIterationCount);
410+
Cipher cipher = createCipher(Cipher.ENCRYPT_MODE, password, salt, iv);
416411
try (
417412
CipherOutputStream cipherStream = new CipherOutputStream(bytes, cipher);
418413
DataOutputStream output = new DataOutputStream(cipherStream)
@@ -455,7 +450,7 @@ public synchronized void save(Path configDir, char[] password, boolean preserveP
455450
byte[] iv = new byte[12];
456451
random.nextBytes(iv);
457452
// encrypted data
458-
byte[] encryptedBytes = encrypt(password, salt, iv, getKdfIterationCountForVersion(CURRENT_VERSION));
453+
byte[] encryptedBytes = encrypt(password, salt, iv);
459454

460455
// size of data block
461456
output.writeInt(4 + salt.length + 4 + iv.length + 4 + encryptedBytes.length);

0 commit comments

Comments
 (0)