Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for elliptical curves #915

Merged
merged 37 commits into from
Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
3a8a7bc
Generate key pairs using encryptor rather than fixed values to
melowe Oct 24, 2019
6c80eb7
ignore push test as fixtures are tricky to generate and this is covered
melowe Oct 24, 2019
088dc82
Add initial AEC encryptor module, pending config integration.
melowe Oct 24, 2019
03ec3eb
Ensure that JACL encryptor is returned despite AEC being available in
melowe Oct 24, 2019
c75aea9
Move payload build to be inner class to control and tighten up creation
melowe Oct 24, 2019
812d318
Add support for encryptor configuration.
melowe Oct 24, 2019
6472d9c
Move config properties into root package to stop moxy generating
melowe Oct 24, 2019
e9c3f1a
Change type to enumeration and not string
melowe Oct 25, 2019
8083f5a
Add type property to factories and filter on that. Allow optional
melowe Oct 28, 2019
d315079
All code changes required to add alternative encryptor implementations,
melowe Nov 1, 2019
3bc9717
remove commented code
melowe Nov 1, 2019
c138411
Rename aec to ec
melowe Nov 1, 2019
0d1c323
avoid null pointer
melowe Nov 1, 2019
60d28a1
Reapplied changes made in initial feature/encryption_alternative_curves
melowe Oct 24, 2019
0ee1c90
Dont provide default encrptor config intenally. Require that config
melowe Nov 5, 2019
533db80
Refactor config processing .
melowe Nov 6, 2019
c1159a2
Remove catch block used for debugging
melowe Nov 6, 2019
5f74fea
explicitly define passwords list as transient to prevent it
melowe Nov 6, 2019
2ee0fbe
Don't store passwords to file system prefer to store in password list
melowe Nov 6, 2019
349fe62
Inject the encryptor into FileSystemKeyPair instead of InlineKeyPair
namtruong Nov 7, 2019
888fa07
Validate that updatepassword requires that the encrpytor type is defi…
melowe Nov 7, 2019
4633556
Remove recursive field check as cant compare different encryptor
melowe Nov 7, 2019
6ea53f3
Catch any error and log during enclave creation.
melowe Nov 7, 2019
05a41b5
Dont validate key presents after unmarshal as this is suppressed unless
melowe Nov 7, 2019
79f178e
Add encryptpr config to config object to deal with cases where not
melowe Nov 7, 2019
56e8522
dont sys out config
melowe Nov 7, 2019
9d926ff
Check config isnt null before setting encryptor.
melowe Nov 7, 2019
cf68cba
Add test for log and throw exception handling.
melowe Nov 8, 2019
a63edeb
Remove constructer that adds default encryptor as defaults are
melowe Nov 8, 2019
318181a
Add hashcode and equals.
melowe Nov 8, 2019
c23bc07
extend Configitem to add recursive equals and hashcode
melowe Nov 8, 2019
ab881d9
Remove whitespace, no fucntional changes,.
melowe Nov 8, 2019
7b0d659
Merge branch 'master' into encryption_alt_curves
melowe Nov 12, 2019
6da2153
Merge branch 'master' into encryption_alt_curves
melowe Nov 12, 2019
81ad2b1
Merge branch 'master' into encryption_alt_curves
melowe Nov 13, 2019
c5e8921
Default encryptor type to NACL. Ensure that one of configfile, uddate…
melowe Nov 14, 2019
ee58618
Set JSON_REDUCE_ANY_ARRAYS on marshaller to stop map marshal returning
melowe Nov 14, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -95,7 +94,7 @@ public void addPeer() throws Exception {
final Path configFile = ElUtil.createAndPopulatePaths(getClass().getResource("/sample-config.json"));
final ConfigurationMixin mixin = new ConfigurationMixin();
try (InputStream in = Files.newInputStream(configFile)) {
final Config config = ConfigFactory.create().create(in, Collections.emptyList());
final Config config = ConfigFactory.create().create(in);
mixin.setConfig(config);
}

Expand All @@ -119,7 +118,7 @@ public void failToAddPeerReturnsFalse() throws Exception {
final Path configFile = ElUtil.createAndPopulatePaths(getClass().getResource("/sample-config.json"));
final ConfigurationMixin mixin = new ConfigurationMixin();
try (InputStream in = Files.newInputStream(configFile)) {
final Config config = ConfigFactory.create().create(in, Collections.emptyList());
final Config config = ConfigFactory.create().create(in);
mixin.setConfig(config);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.quorum.tessera.io.SystemAdapter;
import com.quorum.tessera.passwords.PasswordReader;
import com.quorum.tessera.passwords.PasswordReaderFactory;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
Expand All @@ -33,11 +32,12 @@ 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
// invalid config, but gets picked up by validation later
return;
}

Expand All @@ -48,41 +48,41 @@ public void resolveKeyPasswords(final Config config) {
try {
allPasswords.addAll(Files.readAllLines(input.getPasswordFile(), StandardCharsets.UTF_8));
} catch (final IOException ex) {
//dont do anything, if any keys are locked validation will complain that
//locked keys were provided without passwords
// dont do anything, if any keys are locked validation will complain that
// locked keys were provided without passwords
SystemAdapter.INSTANCE.err().println("Could not read the password file");
}
}

IntStream
.range(0, input.getKeyData().size())
.forEachOrdered(i -> {
if(i < allPasswords.size()) {
input.getKeyData().get(i).withPassword(allPasswords.get(i));
}
});

//decrypt the keys, either using provided passwords or read from CLI
IntStream
.range(0, input.getKeyData().size())
.forEachOrdered(keyNumber -> getSingleKeyPassword(keyNumber, input.getKeyData().get(keyNumber)));
IntStream.range(0, input.getKeyData().size())
.forEachOrdered(
i -> {
if (i < allPasswords.size()) {
input.getKeyData().get(i).withPassword(allPasswords.get(i));
}
});

// decrypt the keys, either using provided passwords or read from CLI
IntStream.range(0, input.getKeyData().size())
.forEachOrdered(keyNumber -> getSingleKeyPassword(keyNumber, input.getKeyData().get(keyNumber)));
}

//TODO: make private
//@VisibleForTesting
// TODO: make private
// @VisibleForTesting
public void getSingleKeyPassword(final int keyNumber, final ConfigKeyPair keyPair) {
final boolean isInline = keyPair instanceof InlineKeypair;
final boolean isFilesystem = keyPair instanceof FilesystemKeyPair;
final boolean isInline = InlineKeypair.class.isInstance(keyPair);
final boolean isFilesystem = FilesystemKeyPair.class.isInstance(keyPair);

if (!isInline && !isFilesystem) {
//some other key type that doesn't use passwords, skip
// some other key type that doesn't use passwords, skip
return;
}

final InlineKeypair inlineKey = isInline ? (InlineKeypair)keyPair : ((FilesystemKeyPair)keyPair).getInlineKeypair();
final InlineKeypair inlineKey =
isInline ? (InlineKeypair) keyPair : ((FilesystemKeyPair) keyPair).getInlineKeypair();

if(inlineKey == null) {
//filesystem key pair that couldn't load the keys, catch in validation later
if (inlineKey == null) {
// filesystem key pair that couldn't load the keys, catch in validation later
return;
}

Expand All @@ -91,8 +91,16 @@ public void getSingleKeyPassword(final int keyNumber, final ConfigKeyPair keyPai
if (isLocked) {
int currentAttemptNumber = MAX_PASSWORD_ATTEMPTS;
while (currentAttemptNumber > 0) {
if (StringUtils.isEmpty(keyPair.getPassword()) || keyPair.getPrivateKey() == null || keyPair.getPrivateKey().contains("NACL_FAILURE")) {
final String attemptOutput = "Attempt " + (MAX_PASSWORD_ATTEMPTS-currentAttemptNumber+1) + " of " + MAX_PASSWORD_ATTEMPTS + ".";
if (Objects.nonNull(keyPair.getPassword()) && !keyPair.getPassword().isEmpty()
|| keyPair.getPrivateKey() == null
|| keyPair.getPrivateKey().contains("NACL_FAILURE")) {

final String attemptOutput =
"Attempt "
+ (MAX_PASSWORD_ATTEMPTS - currentAttemptNumber + 1)
+ " of "
+ MAX_PASSWORD_ATTEMPTS
+ ".";
System.out.println("Password for key[" + keyNumber + "] missing or invalid.");
System.out.println(attemptOutput + " Enter a password for the key");
final String pass = passwordReader.readPasswordFromConsole();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;

public class ConfigConverter implements CommandLine.ITypeConverter<Config> {

Expand All @@ -24,7 +23,7 @@ public Config convert(final String value) throws Exception {
}

try (InputStream in = Files.newInputStream(path)) {
return configFactory.create(in, Collections.emptyList());
return configFactory.create(in);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.quorum.tessera.cli.parsers;

import com.quorum.tessera.config.Config;
import com.quorum.tessera.config.ConfigFactory;
import com.quorum.tessera.config.KeyConfiguration;
import com.quorum.tessera.config.keypairs.ConfigKeyPair;
import com.quorum.tessera.config.util.ConfigFileStore;
import com.quorum.tessera.config.util.JaxbUtil;
import com.quorum.tessera.io.FilesDelegate;
import com.quorum.tessera.io.SystemAdapter;
import org.apache.commons.cli.CommandLine;

Expand All @@ -15,29 +16,42 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import static java.nio.file.StandardOpenOption.APPEND;
import java.util.List;
import java.util.Objects;

import static java.nio.file.StandardOpenOption.CREATE_NEW;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ConfigurationParser implements Parser<Config> {

private List<ConfigKeyPair> newlyGeneratedKeys = Collections.emptyList();
protected static final Set<PosixFilePermission> NEW_PASSWORD_FILE_PERMS =
Stream.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE).collect(Collectors.toSet());

public ConfigurationParser withNewKeys(final List<ConfigKeyPair> newKeys) {
this.newlyGeneratedKeys = Objects.requireNonNull(newKeys);
return this;
private final List<ConfigKeyPair> newlyGeneratedKeys;

private final FilesDelegate filesDelegate;

public ConfigurationParser(List<ConfigKeyPair> newlyGeneratedKeys) {
this(newlyGeneratedKeys, FilesDelegate.create());
}

protected ConfigurationParser(List<ConfigKeyPair> newlyGeneratedKeys, FilesDelegate filesDelegate) {
this.newlyGeneratedKeys = Objects.requireNonNull(newlyGeneratedKeys);
this.filesDelegate = Objects.requireNonNull(filesDelegate);
}

@Override
public Config parse(final CommandLine commandLine) throws IOException {

final ConfigFactory configFactory = ConfigFactory.create();

Config config = null;

final boolean isGeneratingWithKeyVault = commandLine.hasOption("keygen") && commandLine.hasOption("keygenvaulturl");
final boolean isGeneratingWithKeyVault =
commandLine.hasOption("keygen") && commandLine.hasOption("keygenvaulturl");

if (commandLine.hasOption("configfile") && !isGeneratingWithKeyVault) {
final Path path = Paths.get(commandLine.getOptionValue("configfile"));
Expand All @@ -46,17 +60,25 @@ public Config parse(final CommandLine commandLine) throws IOException {
throw new FileNotFoundException(String.format("%s not found.", path));
}

try (InputStream in = Files.newInputStream(path)) {
config = configFactory.create(in, newlyGeneratedKeys);
try (InputStream in = filesDelegate.newInputStream(path)) {
config = JaxbUtil.unmarshal(in, Config.class);

if (!newlyGeneratedKeys.isEmpty()) {
if (config.getKeys() == null) {
config.setKeys(new KeyConfiguration());
config.getKeys().setKeyData(new ArrayList<>());
}
doPasswordStuff(config);
config.getKeys().getKeyData().addAll(newlyGeneratedKeys);
}
}

if (!newlyGeneratedKeys.isEmpty()) {
//we have generated new keys, so we need to output the new configuration
// we have generated new keys, so we need to output the new configuration
output(commandLine, config);
}

ConfigFileStore.create(path);

}

return config;
Expand All @@ -73,6 +95,49 @@ private static void output(CommandLine commandLine, Config config) throws IOExce
} else {
JaxbUtil.marshal(config, SystemAdapter.INSTANCE.out());
}
}

// create a file if it doesn't exist and set the permissions to be only
// read/write for the creator
private void createFile(Path fileToMake) {
boolean notExists = filesDelegate.notExists(fileToMake);
if (notExists) {
filesDelegate.createFile(fileToMake);
filesDelegate.setPosixFilePermissions(fileToMake, NEW_PASSWORD_FILE_PERMS);
}
}

public Config doPasswordStuff(Config config) {

final List<String> newPasswords =
newlyGeneratedKeys.stream().map(ConfigKeyPair::getPassword).collect(Collectors.toList());

if (config.getKeys().getPasswords() != null) {
config.getKeys().getPasswords().addAll(newPasswords);
return config;
}

if (config.getKeys().getPasswordFile() != null) {
Path passwordFile = config.getKeys().getPasswordFile();
createFile(passwordFile);
filesDelegate.write(passwordFile, newPasswords, APPEND);
return config;
}

/*
* Populate transient list of passwords that is consumed by KeyPasswordResolver
*/
if (newPasswords.stream().anyMatch(Objects::nonNull) && config.getKeys().getKeyData() != null) {

final List<String> existingPasswords =
config.getKeys().getKeyData().stream().map(k -> "").collect(Collectors.toList());

existingPasswords.addAll(newPasswords);
config.getKeys().setPasswords(existingPasswords);

return config;
}

return config;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

import com.quorum.tessera.config.Config;
import com.quorum.tessera.config.ConfigFactory;
import com.quorum.tessera.config.keypairs.ConfigKeyPair;

import java.io.InputStream;
import java.util.List;

public class MockConfigFactory implements ConfigFactory {

@Override
public Config create(InputStream configData, List<ConfigKeyPair> newkeys) {
public Config create(InputStream configData) {
Config config = new Config();

return config;
Expand Down
Loading