Kovacic Posted February 28, 2023 Share Posted February 28, 2023 I am trying to validate input to make sure it follows Active Directory password rules, except it should have 10 char. Technically, this should come back as false but it seems to be validating as true... $Password = "Pass1" $result = StringRegExp($Password,"^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[#!@$%^&*()\-_+={}[\]|\\:;<>,.?\/]).{10,16}$") if @Error then Msgbox(0,"error level",@Error) else Msgbox(0,"test",$result) EndIf This is a breakdown of the Regex I am using... ^ # anchors to start of string (?=.*?[a-z]) # lookahead for lowercase (?=.*?[A-Z]) # lookahead for uppercase (?=.*?[0-9]) # lookahead for numbers (?=.*?[#!@$%^&*()\-_+={}[\\]|\:;<>,.?\/]) # lookahead for special characters .{8,14} # the actual capture, also sets boundaries for 8-14 $ # anchors to end of string Where did I go wrong? This should tell me that Pass1 is no good. teodoric666 1 C0d3 is P0etry( ͡° ͜ʖ ͡°) Link to comment Share on other sites More sharing options...
Nine Posted February 28, 2023 Share Posted February 28, 2023 It is working fine here “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Kovacic Posted February 28, 2023 Author Share Posted February 28, 2023 3 minutes ago, Nine said: It is working fine here So its returning an error for you or 0? C0d3 is P0etry( ͡° ͜ʖ ͡°) Link to comment Share on other sites More sharing options...
Nine Posted February 28, 2023 Share Posted February 28, 2023 no @error because your statement is good $result tells you whether it is found or not (0 = not found -- 1 = found) “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Kovacic Posted February 28, 2023 Author Share Posted February 28, 2023 (edited) This isnt what yours looks like? I cant figure out how its different for me Edited February 28, 2023 by Kovacic C0d3 is P0etry( ͡° ͜ʖ ͡°) Link to comment Share on other sites More sharing options...
mistersquirrle Posted February 28, 2023 Share Posted February 28, 2023 Is that not what you are expecting? There's no @error, and there's no match with your RegEx, nothing is returning true. From the StringRegExp helpfile: Returns 1 (match) or 0 (no match). Are you thinking 0 should be true (as it is in some languages)? When I run it I get 0 for $result as well (no match). There's a few AutoIt regex testers, but I personally like using regex101: https://regex101.com/r/81cRXx/1 Running it from there also shows there is no match, everything seems to be working fine from AutoIt as well. We ought not to misbehave, but we should look as though we could. Link to comment Share on other sites More sharing options...
Kovacic Posted February 28, 2023 Author Share Posted February 28, 2023 4 minutes ago, mistersquirrle said: Is that not what you are expecting? There's no @error, and there's no match with your RegEx, nothing is returning true. From the StringRegExp helpfile: Returns 1 (match) or 0 (no match). Are you thinking 0 should be true (as it is in some languages)? When I run it I get 0 for $result as well (no match). There's a few AutoIt regex testers, but I personally like using regex101: https://regex101.com/r/81cRXx/1 Running it from there also shows there is no match, everything seems to be working fine from AutoIt as well. Shoot... Yeah that is what I wanted.. First I got the response mixed up, then I didnt set my test password correct.. ok thank you, yes this works.. my bad. C0d3 is P0etry( ͡° ͜ʖ ͡°) Link to comment Share on other sites More sharing options...
ioa747 Posted February 28, 2023 Share Posted February 28, 2023 maybe help I know that I know nothing Link to comment Share on other sites More sharing options...
Kovacic Posted February 28, 2023 Author Share Posted February 28, 2023 36 minutes ago, ioa747 said: maybe help On this subject, is there any easy way to generate a random string that conforms to that regular expression, even a bunch of random Chars? I can do this by writing up something messy and quick but if there is something that exists already that is tested, I would prefer that. Thanks! C0d3 is P0etry( ͡° ͜ʖ ͡°) Link to comment Share on other sites More sharing options...
mistersquirrle Posted February 28, 2023 Share Posted February 28, 2023 2 minutes ago, Kovacic said: is there any easy way to generate a random string that conforms to that regular expression, even a bunch of random Chars? Check this out, it looks like that it works, first time I've ever looked for something like this: https://www.browserling.com/tools/text-from-regex qz= da^oZv2Ea qu{z#@(=F$>j:rZ ,&Z^d>]l-;s gSR(;,e[Dxy bR1Syog,u,~{-H) We ought not to misbehave, but we should look as though we could. Link to comment Share on other sites More sharing options...
pixelsearch Posted February 28, 2023 Share Posted February 28, 2023 (edited) @Kovacic that's an interesting pattern you shared with us, because the match requires, at least : * A lower case letter * An upper case letter * A digit * A punctuation sign May I suggest, if Active Directory allows it, to use any punctuation sign found in the appropriate POSIX character class, for example : It would simplify the pattern and get rid of the punctuation string found actually in your pattern, which includes the escaped metacharacters, e.g. \ ^ - ] If I'm not mistaken, there are 32 punctuation characters in [:punct:] , all of them found in the interval chr(33) to chr(126) , e.g. 94 characters found from chr(33) to chr(126) -52 for the alphabetical characters (upper & lower) -10 for digits === 32 punctuation characters in [:punct:] @ioa747 : as you can see in the pic above, version 2.5k will have a different context menu compared to version 2.5j but it takes time to rearrange it exactly as I wish... A major improvement will be to save & restore binary data as UTF8 (necessary in some cases), Edited February 28, 2023 by pixelsearch POSIX not PÖSIX (wondering what was keyed to display it like that lol) Musashi, SOLVE-SMART and ioa747 3 Link to comment Share on other sites More sharing options...
Solution Kovacic Posted March 6, 2023 Author Solution Share Posted March 6, 2023 As a quick update to this, I was able to accomplish the goal just by generating a password using the following: Func GetaPass() Do $Pw = Gen2() Until Validate($Pw) = 0 Return $Pw EndFunc ;==>GetaPass Func Gen2() $boop = "" $Beep = "" For $1 = 0 To 11 $boop = Random(1, 4, 1) If $boop = 1 Then $Beep = $Beep & GenSymbol() If $boop = 2 Then $Beep = $Beep & String(Random(0, 9, 1)) If $boop = 3 Then $Beep = $Beep & GenUpper() If $boop = 4 Then $Beep = $Beep & GenLower() Next Return $Beep EndFunc ;==>Gen2 Func GenUpper() Return Chr(Random(65, 90, 1)) EndFunc ;==>GenUpper Func GenLower() Return Chr(Random(97, 122, 1)) EndFunc ;==>GenLower Func GenSymbol() $symnum = Random(1, 7, 1) If $symnum = 1 Then Return "!" If $symnum = 2 Then Return "@" If $symnum = 3 Then Return "$" If $symnum = 4 Then Return ";" If $symnum = 5 Then Return "?" If $symnum = 6 Then Return "%" If $symnum = 7 Then Return "#" EndFunc ;==>GenSymbol Then I validated it with this Func Validate($Val) $result = StringRegExp($Val, "^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[#!@$%^&*()\-_+={}[\]|\\:;<>,.?\/]).{10,16}$") If @error Then Return 1 Else Return 0 EndIf EndFunc ;==>Validate So in short, I generate the password randomly, and run it through a validation process to make sure whatever password comes out fits the bill. I only posed this because I hate it when im looking for a solution and I find a thread that doesn't mention how it was solved. C0d3 is P0etry( ͡° ͜ʖ ͡°) Link to comment Share on other sites More sharing options...
ioa747 Posted March 6, 2023 Share Posted March 6, 2023 glad you made it and thanks for sharing it ! I definitely couldn't do the validation process, but I could make sure that at least 1 GenSymbol, 1 GenUpper, 1 GenLower, 1 Number, will appear expandcollapse popup; https://www.autoitscript.com/forum/topic/209799-regex-validates-as-true-when-it-should-not/?do=findComment&comment=1514606 #include <Array.au3> Global $Pword = PassMaker(12) ConsoleWrite("Validate(" & $Pword & ")=" & Validate($Pword) & @CRLF) ;---------------------------------------------------------------------------------------- Func PassMaker($Length) Local $boop, $Rnt Local $sPass[$Length + 1] $sPass[1] = GenSymbol() $sPass[2] = String(Random(0, 9, 1)) $sPass[3] = GenUpper() $sPass[4] = GenLower() For $i = 5 To $Length $boop = Random(1, 4, 1) Switch $boop Case 1 $Rnt = GenSymbol() Case 2 $Rnt = String(Random(0, 9, 1)) Case 3 $Rnt = GenUpper() Case 4 $Rnt = GenLower() EndSwitch $sPass[$i] = $Rnt Next _ArrayShuffle($sPass, 1) For $i = 1 To $Length $sPass[0] &= $sPass[$i] Next ;~ _ArrayDisplay($sPass) Return $sPass[0] EndFunc ;==>PassMaker ;---------------------------------------------------------------------------------------- Func GenUpper() Return Chr(Random(65, 90, 1)) EndFunc ;==>GenUpper ;---------------------------------------------------------------------------------------- Func GenLower() Return Chr(Random(97, 122, 1)) EndFunc ;==>GenLower ;---------------------------------------------------------------------------------------- Func GenSymbol() $symnum = Random(1, 7, 1) If $symnum = 1 Then Return "!" If $symnum = 2 Then Return "@" If $symnum = 3 Then Return "$" If $symnum = 4 Then Return ";" If $symnum = 5 Then Return "?" If $symnum = 6 Then Return "%" If $symnum = 7 Then Return "#" EndFunc ;==>GenSymbol ;---------------------------------------------------------------------------------------- Func Validate($Val) $result = StringRegExp($Val, "^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[#!@$%^&*()\-_+={}[\]|\\:;<>,.?\/]).{10,16}$") If @error Then Return 1 Else Return 0 EndIf EndFunc ;==>Validate I know that I know nothing Link to comment Share on other sites More sharing options...
pixelsearch Posted March 7, 2023 Share Posted March 7, 2023 (edited) please delete this message thanks Edited March 7, 2023 by pixelsearch Link to comment Share on other sites More sharing options...
pixelsearch Posted March 7, 2023 Share Posted March 7, 2023 (edited) 4 hours ago, ioa747 said: I definitely couldn't do the validation process Me neither. @Kovacic there's an issue with your script because Validate() validates any password. You can reproduct it this way, which accepts "123" as password, when it shouldn't. Local $Password = GetaPass() MsgBox(0, "Done", "Password = " & $Password) Func GetaPass() Do ; $Pw = Gen2() $Pw = "123" Until Validate($Pw) = 0 Return $Pw EndFunc ;==>GetaPass The reason is that there is something wrong with the Validate function. You're calling StringRegExp with 2 parameters only, which means that the 3rd parameter (the flag) is set to 0 (by default) This Mode 0 returns : * 1 (match) * 0 (no match) And @error (in Mode 0) is only used when it's = 2 (Bad pattern) but your pattern is always correct, which means the function always return 0 actually. The return of this function should be based on $result and not on @error value. It should be easy now to fix your code. Edit: alternatively, adding only 2 characters to the script should fix it, without modifying anything else, let's quiz Edited March 7, 2023 by pixelsearch Link to comment Share on other sites More sharing options...
mistersquirrle Posted March 7, 2023 Share Posted March 7, 2023 Here would be my take on your solution @Kovacic, with @ioa747's approach, because I like that and avoids a 'brute force' approach: expandcollapse popup#include <Array.au3> Global $sGeneratedPassword Global $nGenTime Global $hGenerateTimer = TimerInit() For $iPassword = 0 To 9 ; We don't need to use GenerateValidPassword if we're forcing each type into the string manually first, then mixing it up ;~ $sGeneratedPassword = GenerateValidPassword(Random(10, 16, 1), Random(10, 16, 1)) $sGeneratedPassword = GeneratePassword(Random(10, 16, 1), Random(10, 16, 1)) $nGenTime = @extended / 1000 ;~ ConsoleWrite('Password #' & $iPassword & ': ' & $sGeneratedPassword & ' - ' & StringLen($sGeneratedPassword) & ' chars' & @CRLF) ConsoleWrite(StringFormat('Password #%3s: %16s - %s chars in %.2f ms, is valid: %s', _ $iPassword, _ ; Password #%3s $sGeneratedPassword, _ ; %16s StringLen($sGeneratedPassword), _ ; %s chars $nGenTime, _ ; %.2f ms Validate($sGeneratedPassword) _ ; valid: %s ) & @CRLF) Next ConsoleWrite('Wrote ' & $iPassword & ' passwords in ' & Round(TimerDiff($hGenerateTimer), 2) & ' ms' & @CRLF) Func GenerateValidPassword($iMinLength = 10, $iMaxLength = 16) Local $hTimer = TimerInit() Local $iLoops = 0 Local $sPassword Local $bValid = False Do $iLoops += 1 $sPassword = GeneratePassword($iMinLength, $iMaxLength) ; We don't know if this password is valid (aka has at least one lower, UPPER, num and symbol) $bValid = Validate($sPassword) Until $bValid = True Return SetError(0, Int(TimerDiff($hTimer) * 1000), $sPassword) EndFunc ;==>GenerateValidPassword Func GeneratePassword($iMinLength = 10, $iMaxLength = 16) Local Const $iMin = 4, $iMax = 64 Local $hTimer = TimerInit() EnforceMinMax($iMinLength, $iMin, $iMaxLength, $iMax) Local $aPass[$iMaxLength] Local $sPassword $aPass[0] = GenSymbol() $aPass[1] = GenNumber() $aPass[2] = GenUpper() $aPass[3] = GenLower() For $iChar = 4 To Random($iMinLength, $iMaxLength, 1) - 1 ; 0 based, not 1 $iGenType = Random(1, 4, 1) Switch $iGenType Case 1 $aPass[$iChar] = GenSymbol() Case 2 $aPass[$iChar] = GenUpper() Case 3 $aPass[$iChar] = GenLower() Case 4 $aPass[$iChar] = GenNumber() Case Else ConsoleWrite('Error in $iGenType') $iChar -= 1 ContinueLoop EndSwitch Next ;~ ConsoleWrite('$aPass before: ' & _ArrayToString($aPass, '')) _ArrayShuffle($aPass) ;~ ConsoleWrite(', $aPass after: ' & _ArrayToString($aPass, '') & @CRLF) $sPassword = _ArrayToString($aPass, '') Return SetError(0, Int(TimerDiff($hTimer) * 1000), $sPassword) EndFunc ;==>GeneratePassword Func GenUpper($iMinCharIndex = 65, $iMaxCharIndex = 90) Local Const $iMin = 65, $iMax = 90 EnforceMinMax($iMinCharIndex, $iMin, $iMaxCharIndex, $iMax) Return Chr(Random($iMinCharIndex, $iMaxCharIndex, 1)) EndFunc ;==>GenUpper Func GenLower($iMinCharIndex = 97, $iMaxCharIndex = 122) Local Const $iMin = 97, $iMax = 122 EnforceMinMax($iMinCharIndex, $iMin, $iMaxCharIndex, $iMax) Return Chr(Random($iMinCharIndex, $iMaxCharIndex, 1)) EndFunc ;==>GenLower Func GenNumber($iMinNum = 0, $iMaxNum = 9) Local Const $iMin = 0, $iMax = 9 EnforceMinMax($iMinNum, $iMin, $iMaxNum, $iMax) Return Random($iMinNum, $iMaxNum, 1) EndFunc ;==>GenNumber Func VerifyMinMax(ByRef $iMin, ByRef $iMax) If $iMin > $iMax Then Local $iTemp = $iMax ; Store the current min value $iMax = $iMin $iMin = $iTemp ; Restore min value Return False ; Meaning we had to make a change EndIf Return True ; Meaning Min <= Max EndFunc ;==>VerifyMinMax Func EnforceMinMax(ByRef $iMin, $iAbsoluteMin, ByRef $iMax, $iAbsoluteMax) If $iMin < $iAbsoluteMin Then $iMin = $iAbsoluteMin If $iMax > $iAbsoluteMax Then $iMax = $iAbsoluteMax VerifyMinMax($iMin, $iMax) EndFunc ;==>EnforceMinMax Func GenSymbol() Local Const $aSymbols[] = ['#', '!', '@', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '{', '}', '[', ']', '|', '\', ':', ';', '<', '>', ',', '.', '?', '/'] Local Static $iSymbolMax = UBound($aSymbols) - 1 Local $iIndex = Random(0, $iSymbolMax, 1) Return $aSymbols[$iIndex] EndFunc ;==>GenSymbol Func Validate($sVal) Local $bMatch = StringRegExp($sVal, "^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[#!@$%^&*()\-_+={}[\]|\\:;<>,.?\/]).{10,16}$", $STR_REGEXPMATCH) If @error Then Return SetError(1, 0, 0) EndIf ;~ ConsoleWrite('$bMatch: ' & $bMatch & ' - ' & $sVal & @CRLF) Return SetError(0, 0, $bMatch) EndFunc ;==>Validate If you know the format required, creating a generator is a bit easier, but I'm still not sure how you'd really create a reverse regex parser without just creating a bunch of rules/checks for things, and verifying things like positive/negative lookaheads would be very difficult without just brute forcing it. We ought not to misbehave, but we should look as though we could. Link to comment Share on other sites More sharing options...
jugador Posted March 8, 2023 Share Posted March 8, 2023 (edited) for fun shuffle using regex ConsoleWrite(__PasswordGenerator(4) & @crlf) ConsoleWrite(__PasswordGenerator(11) & @crlf) ConsoleWrite(__PasswordGenerator(100) & @crlf) Func __PasswordGenerator($i_Length = 4) If $i_Length < 4 Then Return SetError(1) Local $Base = $i_Length - 4 Local $password = '' Local $temp For $k = 0 To 3 $password = (($k = 0) ? __GetLetter($k) : _ StringRegExpReplace($password, '^(.{' & Random(1, StringLen($password), 1) & '})', '$1 ' & __GetLetter($k))) $password = StringReplace($password, ' ', '') If $Base = 0 Then ContinueLoop $temp = Random(1, $Base, 1) $Base = $Base - $temp If ($k = 3) And $Base > 0 Then $temp = $temp + $Base For $z = 1 To $temp $password = StringRegExpReplace($password, '^(.{' & Random(0, StringLen($password), 1) & '})', '$1 ' & __GetLetter($k)) $password = StringReplace($password, ' ', '') Next Next Return $password EndFunc Func __GetLetter($index) Local $o_Array[] = ['0123456789', '!@#$%;?', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] Local $StrLength = StringLen($o_Array[$index]) Local $o_Num = Random ( 1, $StrLength, 1) If Mod($o_Num, 2) = 0 And ($o_Num < $StrLength) Then $o_Num = $o_Num + 1 Return StringMid($o_Array[$index], $o_Num, 1) EndFunc Edited March 8, 2023 by jugador Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now