Closed ZingerDerGOD closed 1 year ago
Just to clarify few things:
This is scala
code, but should be no difference from java
.
Specific version is: "com.github.curious-odd-man" % "rgxgen" % "1.3"
I have also tried playing around with settings (specificly generation.infinite.repeat
), as with default settings generated strings are reeeally looong...
But overall - it does not solve the issue, as with default regexp generated strings still have inclusion of non-valid characters.
Perfect solution for me would be - using same regex for checking, and for generating the passwords. But in case this issue is "solvable" with just adding custom regexp, used for generating the password - I'm fine wht that too :)
And - yes, apologies, I'm not that good with regexps in general, so I might be overlooking obvious things here. Sorry :)
Atm "solved" the issue by re-generating password... ugly, but will do as a temporary solution, until I'll get some help form you, sir :)
For the reference, my working code:
val rgxGen:RgxGen = new RgxGen(getPasswordRule().passwordGenerationRule);
var props:RgxGenProperties = new RgxGenProperties()
props.setProperty("generation.infinite.repeat", "10");
rgxGen.setProperties(props);
var newPassword = "";
var matches:Boolean = false;
var attempts = 0;
do {
newPassword = rgxGen.generate();
matches = checkStrength(newPassword);
attempts = attempts + 1;
}
while (!matches && attempts < RANDOM_PASSWORD_GENERATION_ATTEMPTS)
if (!matches) {
throw new Exception("ERROR: Password generator failed to generate proper password after " + RANDOM_PASSWORD_GENERATION_ATTEMPTS + " attempts. Please try again.")
}
newPassword
I guess it can be used as a pseudocode, if somebody would need it.
Checking with RANDOM_PASSWORD_GENERATION_ATTEMPTS
< 5 showed quite high error rate (up to 10%), but with 8+ error rate is close to 0% (with 10 attempts - out of 100.000 password generation requests all resulted in success).
Be wary tho that these rates should be valid only for described above strength checks.
Hello!
Thank you for reaching out and reporting this issue. The issue you've described is a known one and it is mentioned among limitations here. Moreover there is already opened ticked for this kind of issue - #63.
The long story short - the problem is that it is quite hard at the moment to handle situation when lookbehind/lookahead should influence/limit possible variations of other parts of expression.
From my current view your case is particularly complex. And most probably will be solved (if I will not find any nicer approach), by just brute-force:
[A-Za-z0-9@$!*#&]{8,25}
Let's keep this ticket open for now and I will think about the solution for this and the previously mentioned ticket, though I don't want to promise that the solution will be in a nearest time available.
I will need to think more about approaching this issue, but most probably I will have quite limited solution with a brute-force approach and some configuration options to fine-tune the process.
The approach you've taken works only by a miracle. The fact is that it currently works as follows:
(?=.*[A-Z])
- first positive lookahead(?=.*[!@#$&*])
(?=.*[0-9])
(?=.*[a-z])
[A-Za-z0-9@$!*#&]{8,25}
This is obviously incorrect approach and the results are also only occasionally might be valid.
There are few ways I see how you can improve this:
First
Generate by final part - [A-Za-z0-9@$!*#&]{8,25}
- and then validate with your whole pattern, if does not match - regenerate. I think it will result in a more successes.
Alternatively
You can change a pattern a bit:
Java test:
String newPattern = "(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z])([A-Z]|[a-z]|[0-9]|[!@#$&*]){8,25}";
Pattern compile = Pattern.compile(newPattern);
RgxGen rgxGen = new RgxGen(newPattern);
RgxGenProperties props = new RgxGenProperties();
props.setProperty("generation.infinite.repeat", "0"); // NOTE this 0 !!!
rgxGen.setProperties(props);
String text;
do {
text = rgxGen.generate();
System.out.println(text);
} while(compile.matcher(text).find());
This tricks RgxGen with the fact, that each alternative has equal probability to be selected for each character generation. And given that you have at least 8 character long password and only 4 groups - the probability for each group to appear is quite high. Though you still need your check. I've ran this sample code above for a several seconds and it did not stop - meaning all generated values matched.
Hope that helps. :)
Good day :)
Ok, then let's hope this will get resolved with the version, that will contain that #63 fix :)
Meanwhile, my 5 cents on your latest comment:
First of all I totally understand that this is a really complicated case of regex for generating a string
.
But this regex is actually quite common for the task it is designed for: validating password complexity
.
So - I'm not saying that you have to get it working or something sir :)
But I do think, that this is (imho) one of the most common use-cases for the generate string out of RegEx
in general :)
Just a couple of cents on why this feature even required
:)
Then, about your last comment.
String newPattern = "(?=.[A-Z])(?=.[!@#$&])(?=.[0-9])(?=.[a-z])([A-Z]|[a-z]|[0-9]|[!@#$&]){8,25}";
First of all - thank you very much for this new RegEx. It works properly for generating, and validating passwords, both way :)
But, just for the information - it does yield wrong passwords sometimes.
Same as with simplified RegEx (^[A-Za-z0-9@$!*#&]{8,25}$
), which I've tried before, and to which I've provided some statistics on errors.
And error rate of new Regex is pretty much the same.
But anyways, it does bring a benefit of using single regex for both generator, and validator, which simplifies things on my end a lot :)
I will need to think more about approaching this issue, but most probably I will have quite limited solution with a brute-force approach and some configuration options to fine-tune the process.
I can speak for myself at least - this would be good enough approach for me, because then I would just rely on the Library to deliver a password, without taking care of these extra checks and complexities. And as Password Generation (at least in my case) is not a streamlined process, but manual on-demand - delays implied by this additional complexity should be more than acceptable.
Thank you very much for your product sir, and I wish you best of luck!
That is very strange that you say it provides same rate of errors. Please check it once again. Because for me it can generate 1000 values without a single one failing in a row.
I'm not sure how do you check pattern in Scala, but in Java there are 2 methods:
matches
- for patterns without lookaroundfind
- for patterns with lookaround.
In other words matches does not work correctly for pattern with lookahead, as you have.For this code:
String newPattern = "(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z])([A-Z]|[a-z]|[0-9]|[!@#$&*]){8,25}";
Pattern compile = Pattern.compile(newPattern);
RgxGen rgxGen = new RgxGen(newPattern);
RgxGenProperties props = new RgxGenProperties();
props.setProperty("generation.infinite.repeat", "0");
rgxGen.setProperties(props);
String text;
for (int i = 0; i < 1000; i++) {
text = rgxGen.generate();
System.out.println(compile.matcher(text).find() + "\t" + text);
}
I get output like:
can confirm Adapted Pattern as described above works like a charm if you use Java
Pattern compile = Pattern.compile(newPattern); compile.matcher(text).find()
to validate your string instead of
String.match(text)
.
P.S. thank you for your hard work.
Describe the bug Consider a common use-case: We have a regex, used to validate a "password" string. F.e.
^(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z])[A-Za-z0-9@$!*#&]{8,25}$
Limits:!@#$&*
)Then, if we try to feed it to the library, and afterwards generate a password, we are getting passwords which are
7'lP|EyCt"S*00?]7A,<(hhjkR9u82v$!TnIs$$RG*x
, or+~WioK%R#6=6IU]r23Y@Zm&GN@#!6nH3ng1s0&vH4
.THen, for the sake of experiment, if we would consider simplifying the workflow by introducing another pattern, which would be used only for
generating the password
, with something more simple, like that:^[A-Za-z0-9@$!*#&]{8,25}$
- we do actually get proper passwords generated, but not every time. As this regex does not qualify any occurrence-times-per-group restrictions, only the overall pattern - generated password might have inclusions from all groups, or might not have... F.e.7GgDIEFsD
,lZcYX6IpgGwOMOO5vQD#pT
. Both generated from single run, using simplified regex.Honestly - I have no ideas of how to tackle this issue nicely, and any advisory/workaround would be as welcomed as the fix.
To Reproduce Steps to reproduce the behavior:
^(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z])[A-Za-z0-9@$!*#&]{8,25}$
Expected behavior Generated string would follow original Regex restrictions.
Environment (please complete the following information):