I am currently using the following code to generate a random password:
static public String randomPasswordGenerator(int n, String valid)
{
char[] pwd = new char[n];
Random rnd = new Random();
for (int i = 0; i < pwd.length; i++)
{
pwd[i] = valid.charAt(rnd.nextInt(valid.length()));
}
return new String(pwd);
}
The valid parameter is set currently as:
String valid = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789#$&%£";
Sometimes when I generate a password I find strange characters being generated, as for an example I can get: n9iB8Qj6inRÂ (where the last char is not included in the valid set)
Any idea why would this happen?
Thanks a lot
EDIT I though it was something related to an encoding problem but while debugging the return string from the above function, I can directly see that strange character. Also, using the set of characters as "#$&%£" can sometimes return all the characters AND also that strange A (example: &%Â&$&#£%#Â&)
Your code as pasted has no bugs and should do precisely what you want it to.
Nevertheless, this almost 100% certainly has to be a character encoding issue.
All characters in your valid string, except the pound symbol, are in the ASCII range of 32-127, and in almost all character encodings in existence, these just work (The string "foo" if encoded into bytes using ASCII and then decoding with UTF-8, or ISO-8859-1, or Win CP252, or just about anything else, is still "foo") – but that pound is not. If you take the string "That'll be £5,- please!", encode it to bytes using, say, ISO-8859-1, and then decode it back to a string using UTF-8, you'll get "That'll be 5,- please!".
So, theorizing for a moment that this string is being encoded using one charset encoding and then decoded using another, that is your bug, but, that bug won't have any effect as long as the characters you are throwing through this buggy process are all in the 32-127 range on the ASCII table.
Thus, you have 2 ways to solve this problem. Either will fix it:
Make sure the list of valid characters contains only ASCII 32-127 characters. For example, remove the pound, make it a minus, or an underscore, or an open parentheses.
Find the place where you are encoding strings to bytes and vice versa, and ensure that you're always explicitly saying which encoding you are using. Then, I strongly suggest you explicitly enforce UTF-8. For example:
BAD:
new FileReader(new File("/path/to/a/file"))
byte[] bytes = .... some bytes ...; String x = new String(bytes);
GOOD:
Files.newBufferedReader(Paths.get("/path/to/a/file")) // case 1
new BufferedReader(new InputStreamReader(new FileInputStream(new File("/path/to/a/file")), StandardCharsets.UTF_8)); // case 2
byte[] bytes = .... some bytes ...; String x = new String(bytes, StandardCharsets.UTF_8);
Though note of course in all these cases you should use try-with-resources to properly close these.
Case 1 is good because the Files API, unlike most other places in the java core libs, is defined as always going with UTF-8 as an encoding (whereas the other places go with 'the platform default', whatever that might be, usually a bad choice), and case 2 and 3 are good because you are explicitly going with UTF-8.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With