diff --git a/java/google/registry/tools/CreateAnchorTenantCommand.java b/java/google/registry/tools/CreateAnchorTenantCommand.java index bef344ead..0f08fc267 100644 --- a/java/google/registry/tools/CreateAnchorTenantCommand.java +++ b/java/google/registry/tools/CreateAnchorTenantCommand.java @@ -72,14 +72,14 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand implements private boolean fee; @Inject - PasswordGenerator passwordGenerator; + StringGenerator passwordGenerator; @Override protected void initMutatingEppToolCommand() { checkArgument(superuser, "This command must be run as a superuser."); findTldForNameOrThrow(InternetDomainName.from(domainName)); // Check that the tld exists. if (isNullOrEmpty(password)) { - password = passwordGenerator.createPassword(PASSWORD_LENGTH); + password = passwordGenerator.createString(PASSWORD_LENGTH); } Money cost = null; diff --git a/java/google/registry/tools/CreateContactCommand.java b/java/google/registry/tools/CreateContactCommand.java index e243495f4..c9fa8619f 100644 --- a/java/google/registry/tools/CreateContactCommand.java +++ b/java/google/registry/tools/CreateContactCommand.java @@ -103,14 +103,14 @@ final class CreateContactCommand extends MutatingEppToolCommand implements Gtech private String password; @Inject - PasswordGenerator passwordGenerator; + StringGenerator passwordGenerator; private static final int PASSWORD_LENGTH = 16; @Override protected void initMutatingEppToolCommand() { if (isNullOrEmpty(password)) { - password = passwordGenerator.createPassword(PASSWORD_LENGTH); + password = passwordGenerator.createString(PASSWORD_LENGTH); } checkArgument(street == null || street.size() <= 3, "Addresses must contain at most 3 street lines."); diff --git a/java/google/registry/tools/CreateDomainCommand.java b/java/google/registry/tools/CreateDomainCommand.java index 74b2c39d8..b1defb5a8 100644 --- a/java/google/registry/tools/CreateDomainCommand.java +++ b/java/google/registry/tools/CreateDomainCommand.java @@ -76,14 +76,14 @@ final class CreateDomainCommand extends MutatingEppToolCommand implements GtechC private String password; @Inject - PasswordGenerator passwordGenerator; + StringGenerator passwordGenerator; private static final int PASSWORD_LENGTH = 16; @Override protected void initMutatingEppToolCommand() { if (isNullOrEmpty(password)) { - password = passwordGenerator.createPassword(PASSWORD_LENGTH); + password = passwordGenerator.createString(PASSWORD_LENGTH); } checkArgument(ns == null || ns.size() <= 13, "There can be at most 13 nameservers."); diff --git a/java/google/registry/tools/PasswordGenerator.java b/java/google/registry/tools/PasswordGenerator.java deleted file mode 100644 index 099496e4b..000000000 --- a/java/google/registry/tools/PasswordGenerator.java +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Domain Registry Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.tools; - -/** Password generator interface. */ -interface PasswordGenerator { - - /** Generates a password of a specified length. */ - String createPassword(int length); -} diff --git a/java/google/registry/tools/RandomPasswordGenerator.java b/java/google/registry/tools/RandomStringGenerator.java similarity index 71% rename from java/google/registry/tools/RandomPasswordGenerator.java rename to java/google/registry/tools/RandomStringGenerator.java index 672ef179c..f41802a74 100644 --- a/java/google/registry/tools/RandomPasswordGenerator.java +++ b/java/google/registry/tools/RandomStringGenerator.java @@ -18,27 +18,26 @@ import static com.google.common.base.Preconditions.checkArgument; import java.util.Random; import javax.inject.Inject; +import javax.inject.Named; -/** Password generator. */ -class RandomPasswordGenerator implements PasswordGenerator { - - private static final String SYMBOLS = - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-="; +/** Random string generator. */ +class RandomStringGenerator extends StringGenerator { private final Random random; @Inject - RandomPasswordGenerator(Random random) { + RandomStringGenerator(@Named("alphabet") String alphabet, Random random) { + super(alphabet); this.random = random; } - /** Generates a password of a specified length. */ + /** Generates a random string of a specified length. */ @Override - public String createPassword(int length) { + public String createString(int length) { checkArgument(length > 0); char[] password = new char[length]; for (int i = 0; i < length; ++i) { - password[i] = SYMBOLS.charAt(random.nextInt(SYMBOLS.length())); + password[i] = alphabet.charAt(random.nextInt(alphabet.length())); } return new String(password); } diff --git a/java/google/registry/tools/RegistryToolModule.java b/java/google/registry/tools/RegistryToolModule.java index 3e0500318..ebfd7224a 100644 --- a/java/google/registry/tools/RegistryToolModule.java +++ b/java/google/registry/tools/RegistryToolModule.java @@ -22,6 +22,8 @@ import java.security.ProviderException; import java.security.SecureRandom; import java.util.Random; +import javax.inject.Named; + /** Dagger module for Registry Tool. */ @Module abstract class RegistryToolModule { @@ -32,7 +34,7 @@ abstract class RegistryToolModule { } @Binds - abstract PasswordGenerator providePasswordGenerator(RandomPasswordGenerator passwordGenerator); + abstract StringGenerator provideStringGenerator(RandomStringGenerator stringGenerator); @Provides static Random provideRandom() { @@ -42,4 +44,10 @@ abstract class RegistryToolModule { throw new ProviderException(e); } } + + @Provides + @Named("alphabet") + static String provideAlphabet() { + return StringGenerator.Alphabets.BASE_64; + } } diff --git a/java/google/registry/tools/SetupOteCommand.java b/java/google/registry/tools/SetupOteCommand.java index effb9869c..5b8adef5b 100644 --- a/java/google/registry/tools/SetupOteCommand.java +++ b/java/google/registry/tools/SetupOteCommand.java @@ -81,7 +81,7 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman private String premiumList = DEFAULT_PREMIUM_LIST; @Inject - PasswordGenerator passwordGenerator; + StringGenerator passwordGenerator; /** * Long registrar names are truncated and then have an incrementing digit appended at the end so @@ -188,16 +188,16 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman // Storing names and credentials in a list of tuples for later play-back. List> registrars = new ArrayList<>(); registrars.add(ImmutableList.of( - registrar + "-1", passwordGenerator.createPassword(PASSWORD_LENGTH), + registrar + "-1", passwordGenerator.createString(PASSWORD_LENGTH), registrar + "-sunrise")); registrars.add(ImmutableList.of( - registrar + "-2", passwordGenerator.createPassword(PASSWORD_LENGTH), + registrar + "-2", passwordGenerator.createString(PASSWORD_LENGTH), registrar + "-landrush")); registrars.add(ImmutableList.of( - registrar + "-3", passwordGenerator.createPassword(PASSWORD_LENGTH), + registrar + "-3", passwordGenerator.createString(PASSWORD_LENGTH), registrar + "-ga")); registrars.add(ImmutableList.of( - registrar + "-4", passwordGenerator.createPassword(PASSWORD_LENGTH), + registrar + "-4", passwordGenerator.createString(PASSWORD_LENGTH), registrar + "-ga")); for (List r : registrars) { diff --git a/java/google/registry/tools/StringGenerator.java b/java/google/registry/tools/StringGenerator.java new file mode 100644 index 000000000..3834ae47e --- /dev/null +++ b/java/google/registry/tools/StringGenerator.java @@ -0,0 +1,44 @@ +// Copyright 2016 The Domain Registry Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; + +/** String generator. */ +abstract class StringGenerator { + + /** A class containing different alphabets used to generate strings. */ + public static class Alphabets { + + /** A URL-safe Base64 alphabet (alphanumeric, hyphen, underscore). */ + public static final String BASE_64 = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"; + + /** An alphanumeric alphabet that omits visually similar characters. */ + public static final String BASE_58 = + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + } + + protected String alphabet; + + StringGenerator(String alphabet) { + checkArgument(!isNullOrEmpty(alphabet), "Alphabet cannot be null or empty."); + this.alphabet = alphabet; + } + + /** Generates a string of a specified length. */ + abstract String createString(int length); +} diff --git a/javatests/google/registry/tools/BUILD b/javatests/google/registry/tools/BUILD index f01c4d359..4325c63cd 100644 --- a/javatests/google/registry/tools/BUILD +++ b/javatests/google/registry/tools/BUILD @@ -28,6 +28,7 @@ java_library( "//third_party/java/joda_money", "//third_party/java/joda_time", "//third_party/java/json_simple", + "//third_party/java/jsr330_inject", "//third_party/java/junit", "//third_party/java/mockito", "//third_party/java/objectify:objectify-v4_1", diff --git a/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java b/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java index 6db43779e..f83d2b0d3 100644 --- a/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java +++ b/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java @@ -29,7 +29,7 @@ public class CreateAnchorTenantCommandTest @Before public void initCommand() { - command.passwordGenerator = new FakePasswordGenerator("abcdefghijklmnopqrstuvwxyz"); + command.passwordGenerator = new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz"); } @Test diff --git a/javatests/google/registry/tools/CreateContactCommandTest.java b/javatests/google/registry/tools/CreateContactCommandTest.java index 21e35a487..d582894e1 100644 --- a/javatests/google/registry/tools/CreateContactCommandTest.java +++ b/javatests/google/registry/tools/CreateContactCommandTest.java @@ -23,7 +23,7 @@ public class CreateContactCommandTest extends EppToolCommandTestCaseNote that consecutive calls to createString will continue where the last call left off in + * the alphabet. + */ +class DeterministicStringGenerator extends StringGenerator { private Iterator iterator; - /** Produces a password from the password source string. */ + /** + * Generates a string using sequential characters in the generator's alphabet, cycling back to the + * beginning of the alphabet if necessary. + */ @Override - public String createPassword(int length) { - checkArgument(length > 0, "Password length must be positive."); + public String createString(int length) { + checkArgument(length > 0, "String length must be positive."); String password = ""; for (int i = 0; i < length; i++) { password += iterator.next(); @@ -37,8 +48,8 @@ class FakePasswordGenerator implements PasswordGenerator { return password; } - public FakePasswordGenerator(String passwordSource) { - checkArgument(!isNullOrEmpty(passwordSource), "Password source cannot be null or empty."); - iterator = Iterators.cycle(charactersOf(passwordSource)); + public DeterministicStringGenerator(@Named("alphabet") String alphabet) { + super(alphabet); + iterator = Iterators.cycle(charactersOf(alphabet)); } } diff --git a/javatests/google/registry/tools/SetupOteCommandTest.java b/javatests/google/registry/tools/SetupOteCommandTest.java index 1ae7d5041..3448d046b 100644 --- a/javatests/google/registry/tools/SetupOteCommandTest.java +++ b/javatests/google/registry/tools/SetupOteCommandTest.java @@ -41,7 +41,8 @@ public class SetupOteCommandTest extends CommandTestCase { ImmutableList passwords = ImmutableList.of( "abcdefghijklmnop", "qrstuvwxyzabcdef", "ghijklmnopqrstuv", "wxyzabcdefghijkl"); - FakePasswordGenerator passwordGenerator = new FakePasswordGenerator("abcdefghijklmnopqrstuvwxyz"); + DeterministicStringGenerator passwordGenerator = + new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz"); @Before public void init() {