How can I create a password? - java

I want to give maybe a million password to some users that should be like:
It must have at least 6 characters
It must have digits and also letters
Should I use Random here? How?

RandomStringUtils from Apache Commons Lang provide some methods to generate a randomized String, that can be used as password.
Here are some examples of 8-characters passwords creation:
// Passwords with only alphabetic characters.
for (int i = 0; i < 8; i++) {
System.out.println(RandomStringUtils.randomAlphabetic(8));
}
System.out.println("--------");
// Passwords with alphabetic and numeric characters.
for (int i = 0; i < 8; i++) {
System.out.println(RandomStringUtils.randomAlphanumeric(8));
}
which creates the following result:
zXHzaLdG
oDtlFDdf
bqPbXVfq
tzQUWuxU
qBHBRKQP
uBLwSvnt
gzBcTnIm
yTUgXlCc
--------
khDzEFD2
cHz1p6yJ
3loXcBau
F6NJAQr7
PyfN079I
8tJye7bu
phfwpY6y
62q27YRt
Of course, you have also methods that may restrict the set of characters allowed for the password generation:
for (int i = 0; i < 8; i++) {
System.out.println(RandomStringUtils.random(8, "abcDEF123"));
}
will create only passwords with the characters a, b, c, D, E, F, 1, 2 or 3:
D13DD1Eb
cac1Dac2
FE1bD2DE
2ab3Fb3D
213cFEFD
3c2FEDDF
FDbFcc1E
b2cD1c11

When using Apache's RandomStringUtils for security reasons (i.e. passwords), it's very important to combine the use of a SecureRandom source:
RandomStringUtils.random(6, 0, 0, true, true, null, new SecureRandom());

Use SecureRandom, it provides a more random passwords.
You can create a single password using something like this (note: untested code).
// put here all characters that are allowed in password
char[] allowedCharacters = {'a','b','c','1','2','3','4'};
SecureRandom random = new SecureRandom();
StringBuffer password = new StringBuffer();
for(int i = 0; i < PASSWORD_LENGTH; i++) {
password.append(allowedCharacters[ random.nextInt(allowedCharacters.length) ]);
}
Note that this does not guarantee that the every password will have both digits and characters.

Here's one that I wrote a while back:
package com.stackoverflow.does.my.code.for.me;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
public class PasswordUtil {
/** Minimum password length = 6 */
public static final int MIN_PASSWORD_LENGTH = 6;
/** Maximum password length = 8 */
public static final int MAX_PASSWORD_LENGTH = 8;
/** Uppercase characters A-Z */
public static final char[] UPPERS = new char[26];
/** Lowercase characters a-z */
public static final char[] LOWERS = new char[26];
/**
* Printable non-alphanumeric characters, excluding space.
*/
public static final char[] SPECIALS = new char[32];
public static final char[] DIGITS = new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
static {
// Static initializer block for populating arrays
int U = 'A';
int l = 'a';
int d = '0';
for (int i = 0; i < 26; i++) {
UPPERS[i] = (char) (U + i);
LOWERS[i] = (char) (l + i);
if (i < 10) {
DIGITS[i] = (char) (d + i);
}
}
int p = 0;
for (int s = 33; s < 127; s++) {
char specialChar = (char) 32;
if (s >= 'a' && s <= 'z')
s = 'z' + 1; // jump over 'a' to 'z'
else if (s >= 'A' && s <= 'Z')
s = 'Z' + 1; // jump over 'A' to 'Z'
else if (s >= '0' && s <= '9')
s = '9' + 1; // jump over '0' to '9'
specialChar = (char) s;
SPECIALS[p] = specialChar;
p++;
}
}
public String generatePassword() {
List<char[]> activeSets = new ArrayList<char[]>(4);
List<char[]> inactiveSets = new ArrayList<char[]>(4);
activeSets.add(UPPERS);
activeSets.add(LOWERS);
activeSets.add(SPECIALS);
activeSets.add(DIGITS);
SecureRandom random = new SecureRandom();
int passwordLength = 5 + random.nextInt(3);
StringBuffer password = new StringBuffer(passwordLength + 1);
for (int p = 0; p <= passwordLength; p++) {
char[] randomSet = null;
if (activeSets.size() > 1) {
int rSet = random.nextInt(activeSets.size());
randomSet = activeSets.get(rSet);
inactiveSets.add(randomSet);
activeSets.remove(rSet);
} else {
randomSet = activeSets.get(0);
inactiveSets.add(randomSet);
activeSets.clear();
activeSets.addAll(inactiveSets);
inactiveSets.clear();
}
int rChar = random.nextInt(randomSet.length);
char randomChar = randomSet[rChar];
password.append(randomChar);
}
return password.toString();
}
}

This is also a nice one:
String password = Integer.toString((int) (Math.random() * Integer.MAX_VALUE), 36);
It however does not guarantee that the password always contains both digits and letters, but most of the aforementioned suggestions also doesn't do that.

What I would do is something like this:
Create two arrays, one with the allowed letters and other with the allowed digits.
Use Random to decide the length of the password.
Use Random to decide whether the next character is a letter or a digit.
Use Random once more to generate an index for the array of letters or digits (depending on wht you obtained in step 3). Append the obtained character to the password.
Repeat from 3 until you have the amount of characters obtained in 2.

This will be the easiest one :)
String char_group = "abcdefghijklmnopqrstuvwxyz";
String digit_group = "123456789";
// first choose a len of pwd
Random ran = new Random();
int pwd_len = ran.nextInt(50); //50 is the max length of password,say
// check that pwd_len is not less than 6
// do the check here
// finally create the password..
StringBuffer pwd = new StringBuffer();
Random RNG = new Random();
for (int i = 0; i < pwd_len ; i++) {
int randomNum = RNG.nextInt(100);
char c = '';
// Here 25% is the ratio of mixing digits
// in the password, you can change 4 to any
// other value to change the depth of mix
// or you can even make it random.
if (randomNum % 4 == 0) {
c = digit_group[randomNum % digit_group.length];
} else {
c = char_group[randomNum % char_group.length];
}
pwd.append(c);
}
return pwd.toString();

A bit late, but I usually use the following code:
private static final int PASSWORD_SIZE = 16;
private static final String VALID_SPECIAL_CHARACTERS = "!##$%&*()_-+=[]{}\\|:/?.,><"; // Note the double \ as escape
private static String createPassword() {
SecureRandom random = new SecureRandom();
StringBuilder password = new StringBuilder();
while (password.length() < PASSWORD_SIZE) {
char character = (char) random.nextInt(Character.MAX_VALUE);
if ((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || VALID_SPECIAL_CHARACTERS.contains(String.valueOf(character))) {
password.append(character);
}
}
return password.toString();
}
There is no guarantee that there will always be a number, special character, lower-case and upper-case character in the password.
This could be enforced by first adding a character and a digit, however this would create passwords that are a bit more predictable.

Here is how you can make sure your generated password meets your password criteria, e.g: in your case, i would use this regex:
<code>String regex = "^(?=[a-zA-Z0-9ñÑ]*\d)(?=[a-zA-Z0-9ñÑ]*[a-z])(?=[a-zA-Z0-9ñÑ]*[A-Z])[a-zA-Z0-9ñÑ]{6,}$"</code>
This regex meets the following criteria:
1.- at least 1 lowerCase letter
2.- at least 1 upperCase letter
3.- at least 1 digit(number)
4.- at least 6 characters (note that adding a number greater than 6 after the comma at the end of the regex, will now meet a criteria that at least 6 characters and a max of whatever you put in there)
<code>char[] char = {'a','b','c','d','e','f','g','h',...};
SecureRandom random = new SecureRandom();
StringBuffer password = new StringBuffer();</code>
while(!password.toString().matches("your regex")){
for(int i = 0; i < 8; i++) {
password.append(char [ random.nextInt(char .length) ]);
}
}
System.out.println(password.toString());
What this code does is that whileyour generated password doesn't meet your criteria, it will loop the for loop over and over.

Implemented a PasswordBuilder. Supports passwrod limit, must have characters and how much of them, char ranges and a list of them.
Usage Example:
System.out.println(new PasswordBuilder().addCharsOption("!##$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).build());
Example result: QU1GY7p+j+-PUW+_
System.out.println(new PasswordBuilder().addCharsOption("!##$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).setSize(5).build());
Example result: %,4NX
Implementation:
//Version=1.0
//Source=https://www.dropbox.com/s/3a4uyrd2kcqdo28/PasswordBuilder.java?dl=0
//Dependencies=java:7 com.google.guava:guava:18.0 commons-lang:commons-lang:2.6
import com.google.common.primitives.Chars;
import org.apache.commons.lang.ArrayUtils;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by alik on 5/26/16.
*/
public class PasswordBuilder {
private int size = 16;
private List<Character> options = new ArrayList<>();
private Map<List<Character>, Integer> musts = new java.util.LinkedHashMap<>();
private SecureRandom secureRandom = new SecureRandom();
public PasswordBuilder() {
}
public PasswordBuilder setSize(int size) {
this.size = size;
return this;
}
public PasswordBuilder addRangeOption(char from, char to, int mustCount) {
List<Character> option = new ArrayList<>(to - from + 1);
for (char i = from; i < to; ++i) {
option.add(i);
}
return addOption(option, mustCount);
}
public PasswordBuilder addCharsOption(String chars, int mustCount) {
return addOption(Chars.asList(chars.toCharArray()), mustCount);
}
public PasswordBuilder addOption(List<Character> option, int mustCount) {
this.options.addAll(option);
musts.put(option, mustCount);
return this;
}
public String build() {
validateMustsNotOverflowsSize();
Character[] password = new Character[size];
// Generate random from musts
for (Map.Entry<List<Character>, Integer> entry : musts.entrySet()) {
for (int i = 0; i < entry.getValue(); i++) {
int charIndex = secureRandom.nextInt(entry.getKey().size());
char c = entry.getKey().get(charIndex);
addChar(password, c);
}
}
// Generate from overall
for (int i = 0; i < password.length; i++) {
if (password[i] != null) continue;
password[i] = options.get(secureRandom.nextInt(options.size()));
}
return new String(ArrayUtils.toPrimitive(password));
}
private void addChar(Character[] password, char c) {
int i;
for (i = secureRandom.nextInt(password.length); password[i] != null; i = secureRandom.nextInt(password.length)) {
}
password[i] = c;
}
private void validateMustsNotOverflowsSize() {
int overallMusts = 0;
for (Integer mustCount : musts.values()) {
overallMusts += mustCount;
}
if (overallMusts > size) {
throw new RuntimeException("Overall musts exceeds the requested size of the password.");
}
}
public static void main(String[] args) {
System.out.println(new PasswordBuilder().addCharsOption("!##$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).build());
System.out.println(new PasswordBuilder().addCharsOption("!##$%&*()_-+=[]{}\\|:/?.,><", 1).addRangeOption('A', 'Z', 1).addRangeOption('a', 'z', 0).addRangeOption('0', '9', 1).setSize(5).build());
}
}

Related

Creating a Character Array with a Certain Number of Vowels and Consonants (Java)

I am trying to create a program that outputs ten lowercase letter characters - five vowels and five consonants. In order to do this, I have started by creating a char array with a range between 'a' and 'z' called letters[] with size 10. Once the array is filled, I will print the output with the use of a format string containing everything in the array.
My question is, how would I make the program output exactly five of each type (and keep the order of the characters printed completely random)? I have considered using the switch statement with a case each for consonants and vowels, but my ideas so far seem over-complicated and inelegant.
Code so far:
char letters[] = new char[10];
for(int i = 0; i < letters.length; i++){ //Open for
letters[i] = (char)(97 + Math.random() * 26);
char idx = letters[i];
System.out.printf("%s",idx);
} //End for
If you don't mind a somewhat more String-related solution, here is one. I am assuming that you don't want any consonant or vowel repeated in the output string, so this algorithm removes letters for consideration once they've been used. It also provides a bit more of a generic letter picker routine that's not really limited to vowels and consonants.
import java.lang.StringBuilder;
public class Shuffler {
public static String CONSONANTS = "bcdfghjklmnpqrstvwxyz";
public static String VOWELS = "aeiou";
/*
* Returns a new string that is a combination of the current string and 'count'
* characters from the source string (using any character in the source string
* no more than one time).
*/
public static String shuffleIntoString(String current, String source, int count) {
if (current == null || source == null || count < 0 || count > source.length()) {
System.out.println("Error in parameters to shuffleIntoString");
return null;
}
StringBuilder retval = new StringBuilder(current); // build up by inserting at random locations
StringBuilder depletedSource = new StringBuilder(source); // remove characters as they are used
for (int i = 0; i < count; i++) {
int pick = (int) (Math.random() * depletedSource.length());
int whereToInsert = (int) (Math.random() * retval.length());
retval = retval.insert(whereToInsert, depletedSource.charAt(pick));
depletedSource.deleteCharAt(pick);
}
return retval.toString();
}
public static void main(String[] args) {
Shuffler shuf = new Shuffler();
for (int i = 0; i < 10; i++) {
String result = shuf.shuffleIntoString("", shuf.CONSONANTS, 5);
result = shuf.shuffleIntoString(result, shuf.VOWELS, 5);
System.out.println(result);
}
}
}
And the output looks like this:
kqoibauzed
uhcawoerib
afdzoemius
yuagocibej
eiuhaokcyq
ouveiawrxn
uyaiveomxn
ruxeoalhij
uraliwfeoc
afoutiesmr
This will achieve what you desire if you are content with using ArrayLists. To generate the random chars you could generate a number within the index of the corresponding char Strings and add the value to the ArrayList. Collections is a helpful Class that you can use to shuffle the list.
List<Character> list = new ArrayList<>();
String consonants = "bcdfghjklmnpqrstvwxyz";
String vowels = "aeiou";
Random r = new Random();
for (int i = 0; i < 5; i++) {
list.add(consonants.charAt(r.nextInt(consonants.length()))); // Add consonant
list.add(vowels.charAt(r.nextInt(vowels.length()))); // Add vowel
}
Collections.shuffle(list);
for (Character c : list) {
System.out.println(c);
}
I don't seen any rules about duplicated but if you want you can remove latters from arrays after selection.
List<Character> vowels = Arrays.asList('a', 'e', 'i', 'o', 'u');
List<Character> consonants = new ArrayList<>();
for (char latter = 'a'; latter <= 'z'; latter++) {
if(!vowels.contains(latter)) {
consonants.add(latter);
}
}
final Random random = new Random();
int vowelsRemain = 5;
int consonantsRemain = 5;
List<Character> result = new ArrayList<>();
while (vowelsRemain > 0 && consonantsRemain > 0) {
final boolean generateVowel = random.nextBoolean();
final char randomLatter;
if(generateVowel) {
randomLatter = vowels.get(random.nextInt(vowels.size()));
vowelsRemain--;
} else {
randomLatter = consonants.get(random.nextInt(consonants.size()));
consonantsRemain--;
}
result.add(randomLatter);
}
while (vowelsRemain > 0) {
final Character randomVowel = vowels.get(random.nextInt(vowels.size()));
result.add(randomVowel);
vowelsRemain--;
}
while (consonantsRemain > 0) {
final Character randomConsonant = consonants.get(random.nextInt(consonants.size()));
result.add(randomConsonant);
consonantsRemain--;
}
System.out.println(result);

How to randomize the case of letters in a string

I want to write some automated tests for web app authentication. The login password is case-sensitive and always contains at least one alphabetic character.
I want to write a test where I randomly change the case of one or more alphabetic characters.
Let's say the password string is "123te123st!".
Now I want to change this string to one which contains at least one uppercase letter. I'm trying to make sure that the login is still case-insensitive and any variation in case will fail to match the password.
Does anybody know a elegant way to do it? I searched already (including Apache Commons) but couldn't find a helper method.
You can look at the randomAlphaNumeric from the RandomStringUtils, although it would seem that you are not guaranteed for it to have an upper case. To go around this, you could get the first lowercase letter and use the .toUpper() method to get it to upper case.
Alternatively, you could generate random numbers between 0 and 9 and 65 and 90 and 97 and 122. The first set should get you random numbers, you could then cast the second number to a character to get your upper case letter(s) and do the same on the last number to get your lower case ones.
That being said, when testing one usually goes for data which is predetermined rather than generating data on the fly, since that would make it easier to debug. Having a simple pool of passwords might also be easier to implement and would also allow you to better test edge cases.
class Case
{
public static void main(String ar[])
{
String s = "upperCase",split[];
split = s.split("");
int len = s.length(),i=0;
while(i!=len)
{
if(split[i].toUpperCase() == split[i])
{
System.out.println("Password Contains One UpperCase Latter");
break;
}
i++;
}
}
}
By using this code u can easily check whether string contain uppercase or not.
if output prints "Password Contains One Uppercase Latter" this message then string contain at least on uppercase.
In this case output would like:
You can use this class to generate random passwords with a constraint on uppercase letters.
import java.util.Random;
public class RandomPasswordGenerator {
private static final String ALPHA_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String ALPHA = "abcdefghijklmnopqrstuvwxyz";
private static final String NUM = "0123456789";
private static final String SPL_CHARS = "!##$%^&*_=+-/";
public static char[] generatePswd(int minLen, int maxLen, int noOfCAPSAlpha,
int noOfDigits, int noOfSplChars) {
if(minLen > maxLen)
throw new IllegalArgumentException("Min. Length > Max. Length!");
if( (noOfCAPSAlpha + noOfDigits + noOfSplChars) > minLen )
throw new IllegalArgumentException
("Min. Length should be atleast sum of (CAPS, DIGITS, SPL CHARS) Length!");
Random rnd = new Random();
int len = rnd.nextInt(maxLen - minLen + 1) + minLen;
char[] pswd = new char[len];
int index = 0;
for (int i = 0; i < noOfCAPSAlpha; i++) {
index = getNextIndex(rnd, len, pswd);
pswd[index] = ALPHA_CAPS.charAt(rnd.nextInt(ALPHA_CAPS.length()));
}
for (int i = 0; i < noOfDigits; i++) {
index = getNextIndex(rnd, len, pswd);
pswd[index] = NUM.charAt(rnd.nextInt(NUM.length()));
}
for (int i = 0; i < noOfSplChars; i++) {
index = getNextIndex(rnd, len, pswd);
pswd[index] = SPL_CHARS.charAt(rnd.nextInt(SPL_CHARS.length()));
}
for(int i = 0; i < len; i++) {
if(pswd[i] == 0) {
pswd[i] = ALPHA.charAt(rnd.nextInt(ALPHA.length()));
}
}
return pswd;
}
private static int getNextIndex(Random rnd, int len, char[] pswd) {
int index = rnd.nextInt(len);
while(pswd[index = rnd.nextInt(len)] != 0);
return index;
}
}
You can try like this:
public class Test{
public static void main(String[] args){
String s = "1a23test12hjsd2"; // Take it as a password
char[] c= s.toCharArray(); //Convert string in chararray
boolean flag= false;
StringBuilder s1= new StringBuilder();
for(int d:c){
if(d>=97 && d<=122 && !flag){ //Converting lowercase to upper case
d=d-32;
flag=true;
}
s1.append((char)d);
}
System.out.println(s1);
}
}
To generate all capitalized variants of a string, it makes sense to scan the string and store the position of each letter in a list. This will let you iterate over the letters while skipping the non-letter characters.
For example, for the string "_a_b_c_", you want to store the positions [1, 3, 5].
Next, make a boolean array of the same length as the list of letter positions. This will represent the positions of letters that have had their case inverted.
To generate the next capitalized variant, pretend that the boolean array represents a binary number in reverse. Add 1 to that boolean number, which means scanning the array from the beginning, flipping each true to false until you reach a false, which you flip to true. As you flip each bit, invert the case of the corresponding character in the string.
Thus, we get the following 23 - 1 = 7 variants of "_a_b_c_":
binary number reversed capitalized variant
001 100 _A_b_c_
010 010 _a_B_c_
011 110 _A_B_c_
100 001 _a_b_C_
101 101 _A_b_C_
110 011 _a_B_C_
111 111 _A_B_C_
Here is a complete Java implementation.
import java.util.*;
import java.io.*;
public class VaryCaps {
int wordLength,
numLetters;
Integer letterPositions[];
boolean inverted[];
StringBuffer buffer;
public VaryCaps(String word) {
wordLength = word.length();
List<Integer> positionList = new ArrayList<Integer>();
for (int i = 0; i < wordLength; ++i) {
if (Character.isLetter(word.charAt(i))) {
positionList.add(i);
}
}
numLetters = positionList.size();
letterPositions = positionList.toArray(new Integer[numLetters]);
inverted = new boolean[numLetters];
buffer = new StringBuffer(word);
}
private void invert(int index) {
int pos = letterPositions[index];
char ch = buffer.charAt(pos);
if (Character.isUpperCase(ch)) {
ch = Character.toLowerCase(ch);
} else {
ch = Character.toUpperCase(ch);
}
buffer.setCharAt(pos, ch);
inverted[index] = !inverted[index];
}
public String next() {
int index = 0;
while (index < numLetters && inverted[index]) {
invert(index++);
}
if (index == numLetters) {
return null;
}
invert(index);
return buffer.toString();
}
public static void main(String[] args) {
VaryCaps rc = new VaryCaps("_a_b_c_");
String s;
while ((s = rc.next()) != null) {
System.out.println(s);
}
}
}

How to guarantee certain characters in a random password

I am using this function to generate a random password of length 11, as seen in this post:
import java.util.Random;
public class RandomPassword {
public static void main(String[] args){
RandomPassword r = new RandomPassword(11);
System.out.print(r.nextString());
}
private static final char[] symbols;
static {
StringBuilder tmp = new StringBuilder();
for (char ch = '0'; ch <= '9'; ++ch)
tmp.append(ch);
for (char ch = 'a'; ch <= 'z'; ++ch)
tmp.append(ch);
for (char ch = 'A'; ch <= 'Z'; ++ch)
tmp.append(ch);
symbols = tmp.toString().toCharArray();
}
private final Random random = new Random();
private final char[] buf;
public RandomPassword(int length) {
if (length < 1)
throw new IllegalArgumentException("length < 1: " + length);
buf = new char[length];
}
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = symbols[random.nextInt(symbols.length)];
return new String(buf);
}
}
However I need to modify it so that I can guarantee at least one capital letter, one number and one lowercase letter. Right now there is the possibility that the password could contain all caps/lowercase/numbers and we need at least one of each to be accepted by AD. Any help is appreciated, thanks.
***I am told that it would be best to loop through in nextString() like this:
public String nextString() {
for (int idx = 0; idx < buf.length; ++idx)
if(buf[buf.length%3].equals(num/lower/cap)){
buf[idx] = symbols[random.nextInt(symbols.length)];
}
.
.
.
return new String(buf);
}
What do you think?
Create a truly random password
See if the random password meets your requirements using a regular expression
If not, pick a random char from the password and modify it to be a randomly chosen
symbol (or number, or uppercase letter)
This would prevent loops and would also have the benefit of being truly random.
Or, if you're ok with losing some entropy you could:
Create four random strings: lowercase (length: 5), uppercase (4), number (1) and symbol (1)
Concatenate the strings
Shuffle the string with Collections.shuffle
I would recommend a regular expresion searching for a set of predifined characters/numbers uppercase/lowercase and a error message
public String getPassword(){
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
byte[] salt = new byte[16];
sr.nextBytes(salt);
return wellformedPassword(salt.toString()) ? salt.toString() : secured(salt.toString());
}
public String secured(String pass){
return string1.replaceFirst(Pattern.quote("[a-z]", "Z");
}
public boolean wellformedPassword(String pass){
return checkRegExp(pass, "\\d")
&& checkRegExp(pass, "[A-Z]")
&& checkRegExp(pass, "[a-z]");
}
public boolean checkRegExp(String str, String pattern){
Pattern p = Pattern.compile(pattern);
Matcher n = p.matcher(str);
return n.find();
}
SHA assure you lowercase letters and numbers, then you just need to turn, one (in my case) or more to upper.
this is a dummy approach wich can be improved. Share your code so i cant edit later my answer for anyone else.
You could get that char and turn it to upper instead of Z but i guess with this you can get started.
Loop over the characters in the array to ensure that each character class is contained within. Then, if it fails, just generate a new random string. This ensures that all are contained and will not fail to validate very often.
This "cheats" (is weaker than it could be), but it meets the usual requirements (or can be modified to meet them):
import java.util.Random;
public class Password {
private static final String UPPER = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
private static final String LOWER = "abcdefghijklmnpqrstuvwxyz";
private static final String NUMBER = "123456789";
private static final String SPECIAL = "!##$%&*+?";
private Random randGen = new Random();
public static void main(String[] argv) {
Password me = new Password();
for (int i = 0; i <= 10; i++) {
me.printPassword();
}
}
private void printPassword() {
StringBuffer buf = new StringBuffer();
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
buf.append(NUMBER.charAt(Math.abs(randGen.nextInt()) % NUMBER.length()));
for (int i = 0; i <= 4; i++) {
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
}
buf.append(UPPER.charAt(Math.abs(randGen.nextInt()) % UPPER.length()));
buf.append(LOWER.charAt(Math.abs(randGen.nextInt()) % LOWER.length()));
System.out.println(buf.toString());
}
}
I had another algorithm that was better, but lost it.
(I like to print out multiple "suggestions" and then pick the one that seems easiest to remember.)
I really don't know how reliable it is but a try
List<Character> listOfUpperCaseLetter = new ArrayList<Character>();
for(int i = 65;i<91;i++){
char ch = (char)i;
listOfUpperCaseLetter.add(ch);
}
List<Character> listOfLowerCaseLetter = new ArrayList<Character>();
for(int i = 97;i<123;i++){
char ch = (char)i;
listOfLowerCaseLetter.add(ch);
}
List<Integer> listOfInt = new ArrayList<Integer>();
for(int i =0;i<10;i++){
listOfInt.add(i);
}
StringBuilder br = new StringBuilder();
Collections.shuffle(listOfLowerCaseLetter);
Collections.shuffle(listOfUpperCaseLetter);
Collections.shuffle(listOfInt);
br.append(listOfUpperCaseLetter.get(0));
br.append(listOfLowerCaseLetter.get(1));
br.append(listOfLowerCaseLetter.get(3));
br.append(listOfInt.get(1));
br.append(listOfInt.get(0));
br.append(listOfLowerCaseLetter.get(2));
br.append(listOfUpperCaseLetter.get(1));
br.append(listOfLowerCaseLetter.get(0));
br.append(listOfUpperCaseLetter.get(2));
br.append(listOfInt.get(2));
System.out.println(br.toString());
I simply added an if/else statement saying to add certain members of the symbols array (0-10, 11-35, 36-61). This guarantees what is needed. Sometimes the simplest answer is the best answer. Thanks for the ideas.
if (idx == 0){
buf[idx] = symbols[random.nextInt(10)];
}else if (idx == 1){
buf[idx] = symbols[10 + random.nextInt(35-10+1)];
}else if(idx == 2){
buf[idx] = symbols[36 + random.nextInt(61-36+1)];
}else{
buf[idx] = symbols[random.nextInt(symbols.length)];
}

Random password generation

I have written a code for random password generation.There are a string from where i have to make the password.so i try to categorize the string according to uppercase array , lower case array and digit array. but here comes a problem when..
for(int k=0;k<Length;k++){
if(asc[k]>=65 && asc[k]<=90){
UpperCase[k]=(char)asc[k];
}
else if(asc[k]>=48 && asc[k]<=57){
Digit[k]=(char)asc[k];
}
else {
Mixed[k]=(char)asc[k];
}
}
is executed it counts some space which i don't want.coding looks like ugly sry for my poor coding.i know there is a lot more way to solve it but i want to go through this.here is my code. here is my code
import java.util.Random;
public class Randompassgeneration
{
final int MAX_LENGTH = 20;
final int MIN_LENGTH = 3;
char[] password=new char[25];
int [] asc=new int[18];
char[] UpperCase=new char[25];
char[] Digit=new char[25];
char[] Mixed=new char[25];
public void generate(String allowedCharacters)
{
int Length=allowedCharacters.length();
for (int i=0;i<Length;i++)
{
asc[i]=(int)allowedCharacters.charAt(i);
}
for (int k=0;k<Length;k++)
{
if (asc[k]>=65 && asc[k]<=90)
{
UpperCase[k]=(char)asc[k];
}
else if (asc[k]>=48 && asc[k]<=57)
{
Digit[k]=(char)asc[k];
}
else
{
Mixed[k]=(char)asc[k];
}
}
String rp=null;
StringBuilder Strbld=new StringBuilder();
Random rnd=new Random();
int ranStrLen=rnd.nextInt(MAX_LENGTH - MIN_LENGTH + 1) + MIN_LENGTH;
Strbld.append(UpperCase[rnd.nextInt(UpperCase.length)]);
Strbld.append(Digit[rnd.nextInt(Digit.length)]);
for (int m=0; m<ranStrLen-2; m++)
{
Strbld.append(Mixed[rnd.nextInt(Mixed.length)]);
}
System.out.print(ranStrLen +"->"+ Strbld.toString());
}
public static void main(String[] args)
{
String allowedCharacters = "weakPasSWorD1234$*";
Randompassgeneration t=new Randompassgeneration();
t.generate(allowedCharacters);
}
}
Any kind of suggestion?
I would generate the minimum number of characters, digits and symbols. Fill the other characters randomly and shuffle the result. This way it will comply with your minimum requirements with a minimum of effort.
public static String passwordGenerator() {
List<Character> chars = new ArrayList<>();
Random rand = new Random();
// min number of digits
for (int i = 0; i < 1; i++) chars.add((char) ('0' + rand.nextInt(10)));
// min number of lower case
for (int i = 0; i < 2; i++) chars.add((char) ('a' + rand.nextInt(26)));
// min number of upper case
for (int i = 0; i < 1; i++) chars.add((char) ('A' + rand.nextInt(26)));
// min number of symbols
String symbols = "!\"$%^&*()_+{}:#~<>?,./;'#][=-\\|'";
for (int i = 0; i < 1; i++) chars.add(symbols.charAt(rand.nextInt(symbols.length())));
// fill in the rest
while (chars.size() < 8) chars.add((char) ('!' + rand.nextInt(93)));
// appear in a random order
Collections.shuffle(chars);
// turn into a String
char[] arr = new char[chars.size()];
for (int i = 0; i < chars.size(); i++) arr[i] = chars.get(i);
return new String(arr);
}
public static void main(String... args) {
for (int i = 0; i < 100; i++)
System.out.println(passwordGenerator());
}
"is executed it counts some space which i don't want"
The white space is beacuse of your For loop
You were using the variable k for all the arrays,which resulted into the incremented value of k each time.So,this was making "gaps" between your arrays.
Change it to:
int point1=0,point2=0,point3=0;
for (int k=0;k<Length;k++)
{
if (asc[k]>=65 && asc[k]<=90)
{
UpperCase[point1]=(char)asc[k];point1++;
continue;
}
else if (asc[k]>=48 && asc[k]<=57)
{
Digit[point2]=(char)asc[k];point2++;
continue;
}
else
{
Mixed[point3]=(char)asc[k];point3++;
}
}
System.out.println(UpperCase);
System.out.println(Digit);
System.out.println(Mixed);
OutPut:
PSWD
1234
weakasor$*
Ok if not mistaken you want to parse the password generated and want put them in separate array. Here is the snippet for uppercase.
ArrayList<Character> uppercase = new ArrayList<Character>();
char pass[] = password.toCharArray();
for(char c: pass){
if(Character.isUpperCase(c))
uppercase.add(c);
}
If you want a random string, you could do:
public String getRandomString(){
return UUID.randomUUID().toString();
}
If you want to make it consistent with some source String, you could do:
public String getConsistentHash(String source){
return UUID.nameUUIDFromBytes(source.getBytes()).toString();
}
This latter method will return the same String for the same source String.
If there is a only a limited set of characters you want to use, you could just replace the unwanted chars. Suppose you have have created "randomString" as above, you create "randomString1" with:
randomString1 = UUID.fromString(randomString);
Now replace the unwanted chars in "randomString" with the chars in "randomString1". You could repeat this if necessary.
If you do not care for a minimum size/spread, you could just remove the chars.
Good luck.

count specific characters in a string (Java)

I have a homework assignment to count specific chars in string.
For example: string = "America"
The output should be = a appear 2 times, m appear 1 time, e appear 1 time, r appear 1 time, i appear 1 time and c appear 1 time
public class switchbobo {
/**
* #param args
*/ // TODO Auto-generated method stub
public static void main(String[] args){
String s = "BUNANA";
String lower = s.toLowerCase();
char[] c = lower.toCharArray(); // converting to a char array
int freq =0, freq2 = 0,freq3 = 0,freq4=0,freq5 = 0;
for(int i = 0; i< c.length;i++) {
if(c[i]=='a') // looking for 'a' only
freq++;
if(c[i]=='b')
freq2++;
if (c[i]=='c') {
freq3++;
}
if (c[i]=='d') {
freq4++;
}
}
System.out.println("Total chars "+c.length);
if (freq > 0) {
System.out.println("Number of 'a' are "+freq);
}
}
}
code above is what I have done, but I think it is not make sense to have 26 variables (one for each letter). Do you guys have alternative result?
Obviously your intuition of having a variable for each letter is correct.
The problem is that you don't have any automated way to do the same work on different variables, you don't have any trivial syntax which helps you doing the same work (counting a single char frequency) for 26 different variables.
So what could you do? I'll hint you toward two solutions:
you can use an array (but you will have to find a way to map character a-z to indices 0-25, which is somehow trivial is you reason about ASCII encoding)
you can use a HashMap<Character, Integer> which is an associative container that, in this situation, allows you to have numbers mapped to specific characters so it perfectly fits your needs
You can use HashMap of Character key and Integer value.
HashMap<Character,Integer>
iterate through the string
-if the character exists in the map get the Integer value and increment it.
-if not then insert it to map and set the integer value for 0
This is a pseudo code and you have to try coding it
I am using a HashMap for the solution.
import java.util.*;
public class Sample2 {
/**
* #param args
*/
public static void main(String[] args)
{
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
String test = "BUNANA";
char[] chars = test.toCharArray();
for(int i=0; i<chars.length;i++)
{
if(!map.containsKey(chars[i]))
{
map.put(chars[i], 1);
}
map.put(chars[i], map.get(chars[i])+1);
}
System.out.println(map.toString());
}
}
Produced Output -
{U=2, A=3, B=2, N=3}
In continuation to Jack's answer the following code could be your solution. It uses the an array to store the frequency of characters.
public class SwitchBobo
{
public static void main(String[] args)
{
String s = "BUNANA";
String lower = s.toLowerCase();
char[] c = lower.toCharArray();
int[] freq = new int[26];
for(int i = 0; i< c.length;i++)
{
if(c[i] <= 122)
{
if(c[i] >= 97)
{
freq[(c[i]-97)]++;
}
}
}
System.out.println("Total chars " + c.length);
for(int i = 0; i < 26; i++)
{
if(freq[i] != 0)
System.out.println(((char)(i+97)) + "\t" + freq[i]);
}
}
}
It will give the following output:
Total chars 6
a 2
b 1
n 2
u 1
int a[]=new int[26];//default with count as 0
for each chars at string
if (String having uppercase)
a[chars-'A' ]++
if lowercase
then a[chars-'a']++
public class TestCharCount {
public static void main(String args[]) {
String s = "america";
int len = s.length();
char[] c = s.toCharArray();
int ct = 0;
for (int i = 0; i < len; i++) {
ct = 1;
for (int j = i + 1; j < len; j++) {
if (c[i] == ' ')
break;
if (c[i] == c[j]) {
ct++;
c[j] = ' ';
}
}
if (c[i] != ' ')
System.out.println("number of occurance(s) of " + c[i] + ":"
+ ct);
}
}
}
maybe you can use this
public static int CountInstanceOfChar(String text, char character ) {
char[] listOfChars = text.toCharArray();
int total = 0 ;
for(int charIndex = 0 ; charIndex < listOfChars.length ; charIndex++)
if(listOfChars[charIndex] == character)
total++;
return total;
}
for example:
String text = "america";
char charToFind = 'a';
System.out.println(charToFind +" appear " + CountInstanceOfChar(text,charToFind) +" times");
Count char 'l' in the string.
String test = "Hello";
int count=0;
for(int i=0;i<test.length();i++){
if(test.charAt(i)== 'l'){
count++;
}
}
or
int count= StringUtils.countMatches("Hello", "l");

Categories

Resources