com.quorum.tessera.cli.keypassresolver.CliKeyPasswordResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cli-api Show documentation
Show all versions of cli-api Show documentation
Tessera is a stateless Java system that is used to enable the encryption, decryption, and distribution of private transactions for Quorum.
package com.quorum.tessera.cli.keypassresolver;
import com.quorum.tessera.config.*;
import com.quorum.tessera.config.keypairs.ConfigKeyPair;
import com.quorum.tessera.config.keys.KeyEncryptor;
import com.quorum.tessera.config.keys.KeyEncryptorFactory;
import com.quorum.tessera.config.util.KeyDataUtil;
import com.quorum.tessera.passwords.PasswordReader;
import com.quorum.tessera.passwords.PasswordReaderFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CliKeyPasswordResolver implements KeyPasswordResolver {
private static final int MAX_PASSWORD_ATTEMPTS = 2;
private final PasswordReader passwordReader;
public CliKeyPasswordResolver() {
this(PasswordReaderFactory.create());
}
public CliKeyPasswordResolver(final PasswordReader passwordReader) {
this.passwordReader = Objects.requireNonNull(passwordReader);
}
@Override
public void resolveKeyPasswords(final Config config) {
final KeyConfiguration input = config.getKeys();
if (input == null) {
// invalid config, but gets picked up by validation later
return;
}
final List allPasswords = new ArrayList<>();
if (input.getPasswords() != null) {
allPasswords.addAll(
input.getPasswords().stream().map(String::toCharArray).collect(Collectors.toList())
);
} else if (input.getPasswordFile() != null) {
try {
allPasswords.addAll(
Files.readAllLines(input.getPasswordFile(), StandardCharsets.UTF_8)
.stream()
.map(String::toCharArray)
.collect(Collectors.toList())
);
} catch (final IOException ex) {
// dont do anything, if any keys are locked validation will complain that
// locked keys were provided without passwords
System.err.println("Could not read the password file");
}
}
List keyPairs = input.getKeyData();
IntStream.range(0, input.getKeyData().size())
.forEachOrdered(
i -> {
if (i < allPasswords.size()) {
keyPairs.get(i).setPassword(allPasswords.get(i));
}
});
// decrypt the keys, either using provided passwords or read from CLI
EncryptorConfig encryptorConfig =
Optional.ofNullable(config.getEncryptor())
.orElse(
new EncryptorConfig() {
{
setType(EncryptorType.NACL);
}
});
final KeyEncryptor keyEncryptor = KeyEncryptorFactory.newFactory().create(encryptorConfig);
IntStream.range(0, input.getKeyData().size())
.forEachOrdered(
keyNumber -> getSingleKeyPassword(keyNumber, input.getKeyData().get(keyNumber), keyEncryptor));
}
// TODO: make private
// @VisibleForTesting
public void getSingleKeyPassword(final int keyNumber, final KeyData keyPair, final KeyEncryptor keyEncryptor) {
final boolean isInline = KeyDataUtil.isInline(keyPair);
final boolean isFilesystem = KeyDataUtil.isFileSystem(keyPair);
if (!isInline && !isFilesystem) {
// some other key type that doesn't use passwords, skip
return;
}
final boolean isLocked = KeyDataUtil.isLocked(keyPair);
if (isLocked) {
ConfigKeyPair configKeyPair = KeyDataUtil.unmarshal(keyPair, keyEncryptor);
int currentAttemptNumber = MAX_PASSWORD_ATTEMPTS;
while (currentAttemptNumber > 0) {
if (Objects.isNull(configKeyPair.getPassword())
|| configKeyPair.getPassword().length == 0
|| Optional.ofNullable(configKeyPair.getPrivateKey())
.filter(s -> s.contains("NACL_FAILURE"))
.isPresent()) {
final String attemptOutput =
"Attempt "
+ (MAX_PASSWORD_ATTEMPTS - currentAttemptNumber + 1)
+ " of "
+ MAX_PASSWORD_ATTEMPTS
+ ".";
System.out.printf("Password for key[%s] missing or invalid.", keyNumber);
System.out.println();
System.out.printf("%s Enter a password for the key", attemptOutput);
System.out.println();
final char[] pass = passwordReader.readPasswordFromConsole();
configKeyPair.withPassword(pass);
keyPair.setPassword(pass);
}
currentAttemptNumber--;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy