From 52ccfaac0cb59163c408e1d465f0dffa40f1062b Mon Sep 17 00:00:00 2001 From: nnesic Date: Tue, 10 Nov 2015 17:22:31 +0000 Subject: [PATCH] CLOUDSTACK-9052 Shuffling the password to avoid having a subset of characters in fixed positions. --- .../com/cloud/utils/PasswordGenerator.java | 25 ++++++++---- .../cloud/utils/PasswordGeneratorTest.java | 39 +++++++++++++++---- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/PasswordGenerator.java b/utils/src/main/java/com/cloud/utils/PasswordGenerator.java index 0d791431b07e..3ba54f2fa9b5 100644 --- a/utils/src/main/java/com/cloud/utils/PasswordGenerator.java +++ b/utils/src/main/java/com/cloud/utils/PasswordGenerator.java @@ -20,6 +20,9 @@ package com.cloud.utils; import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Random; /** @@ -48,14 +51,19 @@ public static String generateRandomPassword(int num) { password.append(generateAlphaNumeric(r)); } } else { - // Generate random 3-character string with a lowercase character, - // uppercase character, and a digit - password.append(generateLowercaseChar(r)).append(generateUppercaseChar(r)).append(generateDigit(r)); - - // Generate a random n-character string with only lowercase - // characters - for (int i = 0; i < num - 3; i++) { - password.append(generateLowercaseChar(r)); + List passwordChars = new ArrayList(); + passwordChars.add(generateLowercaseChar(r)); + passwordChars.add(generateUppercaseChar(r)); + passwordChars.add(generateDigit(r)); + + for (int i = passwordChars.size(); i < num; i++) { + passwordChars.add(generateAlphaNumeric(r)); + } + + Collections.shuffle(passwordChars, new SecureRandom()); + + for (char c : passwordChars) { + password.append(c); } } @@ -87,4 +95,5 @@ public static String generatePresharedKey(int numChars) { return psk.toString(); } + } diff --git a/utils/src/test/java/com/cloud/utils/PasswordGeneratorTest.java b/utils/src/test/java/com/cloud/utils/PasswordGeneratorTest.java index 413b86618c84..e71436d9b361 100644 --- a/utils/src/test/java/com/cloud/utils/PasswordGeneratorTest.java +++ b/utils/src/test/java/com/cloud/utils/PasswordGeneratorTest.java @@ -30,13 +30,36 @@ public void generateRandomPassword() { Assert.assertTrue(PasswordGenerator.generateRandomPassword(1).length() == 3); Assert.assertTrue(PasswordGenerator.generateRandomPassword(5).length() == 5); String password = PasswordGenerator.generateRandomPassword(8); - // TODO: this might give more help to bruteforcing than desired - // the actual behavior is that the first character is a random lowercase - // char - Assert.assertTrue(Character.isLowerCase(password.charAt(0))); - // the second character is a random upper case char - Assert.assertTrue(Character.isUpperCase(password.charAt(1))); - // and the third is a digit - Assert.assertTrue(Character.isDigit(password.charAt(2))); + + Assert.assertTrue(containsDigit(password)); + Assert.assertTrue(containsLowercase(password)); + Assert.assertTrue(containsUppercase(password)); + } + + private boolean containsUppercase(String password) { + for (char c : password.toCharArray()) { + if (Character.isUpperCase(c)) { + return true; + } + } + return false; + } + + private boolean containsLowercase(String password) { + for (char c : password.toCharArray()) { + if (Character.isLowerCase(c)) { + return true; + } + } + return false; + } + + private boolean containsDigit(String password) { + for (char c : password.toCharArray()) { + if (Character.isDigit(c)) { + return true; + } + } + return false; } }