Password Strength Meter

Share your advanced PureBasic knowledge/code with the community.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 345
Joined: Sat Dec 25, 2004 2:37 pm

Password Strength Meter

Post by thyphoon »

Hello

i would like to share my little code.
You can switch the password area from Password Mode to text Mode and back. And you have an information about Password Strength

if you have some suggestion or comment , tell me all !

best regards and excuse me for my bad english)

Edit:2008/08/04 18h30
  • -Correct Too Short info
    -Add switch text in toogle button "abc" to "***" and reverse
    -the password is tested only when eventype()=#PB_EventType_Change

Code: Select all

#W_PassWord = 0

;Gadget
Enumeration
	#G_Password_Pass
    #G_Password_Toggle
    #G_Password_Check
    #G_Password_Pass_Txt
    #G_Password_Ok
    #G_Password_Cancel
EndEnumeration

Global Key.s

;********************
;Function
;********************

Procedure Match(exp.s, txt.s)
	If CreateRegularExpression(0, exp) And MatchRegularExpression(0, txt)
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf
EndProcedure

Procedure.s DelRepetition(pLen.l, str.s)
	res.s = ""
	For i = 1 To Len(str)
		repeated = #False
		
		For j = 1 To pLen
			If Mid(Str, i, j) = Mid(Str, i + j, j)
				repeated = #True : 
				i = i + j-1
			EndIf
		Next
		If repeated = #False
			res + Mid(str, i, 1)
		EndIf
		
	Next i
	ProcedureReturn res
EndProcedure

Procedure.l passwordStrength(password.s)
	;Source:http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
	score.l = 0
	
	;password < 4
	If (Len(password)<5)
		score-50
	EndIf
	
	;//password == username
	;If (password.toLowerCase()==username.toLowerCase()) Return badPass
	
	;//password length
	score + Len(password)*4
	score + (Len(DelRepetition(1, password))-Len(password) )*1
	score + (Len(DelRepetition(2, password))-Len(password) )*1
	score + (Len(DelRepetition(3, password))-Len(password) )*1
	score + (Len(DelRepetition(4, password))-Len(password) )*1
	score + (Len(DelRepetition(5, password))-Len(password) )*1
	
	;//password has 3 numbers
	If Match("(.*[0-9].*[0-9].*[0-9])", password) : score + 5 : EndIf
	
	;//password has 2 sybols
	If Match("(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])", password) : score + 5 : EndIf
	
	;//password has Upper And Lower chars
	If Match("([a-z].*[A-Z])|([A-Z].*[a-z])", password) : score + 10 : EndIf
	
	;//password has number And chars
	If Match("([a-zA-Z])", password) And Match("([0-9])", password) : score + 15 : EndIf
	
	;//password has number And symbol
	If Match("([!,@,#,$,%,^,&,*,?,_,~])", password) And Match("([0-9])", password) : score + 15 : EndIf
	
	;//password has char And symbol
	If Match("([!,@,#,$,%,^,&,*,?,_,~])", password) And Match("([a-zA-Z])", password) : score + 15 : EndIf
	
	;//password is just a nubers Or chars
	If match("^\w+$", password) Or match("^\d+$", password) : score-10 : EndIf
	
	;//verifing 0 < score < 100
	;if (score<0) : Debug "very Bad" : EndIf
	;If (score>100) : Debug "Perfect" : EndIf
	;If (score = 0 And score<34) : Debug " bad" : EndIf
	;If (score = 34 And score<68) : Debug " good" : EndIf
	;If (score = 68 And score<100) : Debug " strong" : EndIf
	ProcedureReturn score
EndProcedure

Procedure TestPassword(Gdt.l, Pass.s)
	Protected Score.l
	If IsGadget(Gdt)
		Score.l = passwordStrength(Pass)
		If (Score<-40) : SetGadgetText(Gdt, "Too short (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, #Red) : EndIf
		If (Score> = -40 And Score<0) : SetGadgetText(Gdt, "very Bad (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, #Red) : EndIf
		If (Score> = 0 And score<34) : SetGadgetText(Gdt, " bad (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, $0033FF) : EndIf
		If (Score> = 34 And score<68) : SetGadgetText(Gdt, " good (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, $006600) : EndIf
		If (Score> = 68 And score<100) : SetGadgetText(Gdt, " strong (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, $66FF66) : EndIf
		If (Score>100) : SetGadgetText(Gdt, "Perfect (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, #Green) : EndIf
	EndIf
EndProcedure


;Gdt=Gadget who display password / GdtToggle= gadget who sitch password display / GdtCont= If Gdt is in a container gadget
Procedure TogglePassword(Gdt.l, GdtToggle.l, GdtCont.l = -1)
	Protected tmppass.s, tmpx.l, tmpy.l, tmpw.l, tmph.l
	tmppass.s = GetGadgetText(Gdt)
	tmpx = GadgetX(Gdt)
	tmpy = GadgetY(Gdt)
	tmpw = GadgetWidth(Gdt)
	tmph = GadgetHeight(Gdt)
	FreeGadget(Gdt)
	If GdtCont>-1
		OpenGadgetList(GdtCont)
	EndIf
	If GetGadgetState(GdtToggle) = 0
		StringGadget(Gdt, tmpx, tmpy, tmpw, tmph, "", #PB_String_Password)
		SetGadgetText(GdtToggle, "abc")
	Else
		StringGadget(Gdt, tmpx, tmpy, tmpw, tmph, "")
		SetGadgetText(GdtToggle, "***")
	EndIf
	If GdtCont>-1
		CloseGadgetList()
	EndIf
	SetGadgetText(Gdt, tmppass)
EndProcedure

;********************
;Windows
;********************
Procedure OpenWindowPassword()
	OpenWindow(#W_PassWord, 0, 0, 400, 250, "Password", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
	CreateGadgetList(WindowID(#W_PassWord))
	
	TextGadget(#G_Password_Pass_Txt, 10, 55, WindowWidth(#W_PassWord)-20, 20, "Your Master Password")
	StringGadget(#G_Password_Pass, 10, 80, WindowWidth(#W_PassWord)-60, 20, "", #PB_String_Password)
	TextGadget(#G_Password_Check, 10, 110, WindowWidth(#W_PassWord)-60, 20, "", #PB_Text_Center | #PB_Text_Border)
	;SetGadgetAttribute(#G_Password_Pass, #PB_String_Password , 0) //ça n'existe pas pour l'instant dommage
	ButtonGadget(#G_Password_Toggle, WindowWidth(#W_PassWord)-40, 80, 40, 20, "abc", #PB_Button_Toggle)
	ButtonGadget(#G_Password_Ok, 10, WindowHeight(#W_PassWord)-30, 60, 20, "Ok")
	ButtonGadget(#G_Password_Cancel, WindowWidth(#W_PassWord)-70, WindowHeight(#W_PassWord)-30, 60, 20, "Cancel")
	
EndProcedure

Procedure CloseWindowPassword(W_Parent)
	DisableWindow(W_Parent, 0)
EndProcedure

Procedure WindowPasswordLoop()
	Protected EventID.l, Quit.b, ret.l
	OpenWindowPassword()
	Repeat
		EventID = WaitWindowEvent()
		Select(EventID)
			Case #PB_Event_Repaint
				;DrawWindowHead(#W_Icon)
			Case #PB_Event_Menu
			Case #PB_Event_Gadget
				
				Select EventGadget()
					Case #G_Password_Toggle
						TogglePassword(#G_Password_Pass, #G_Password_Toggle)
					Case #G_Password_Pass
						If EventType() = #PB_EventType_Change
							TestPassword(#G_Password_Check, GetGadgetText(#G_Password_Pass))
						EndIf
					Case #G_Password_Ok
						Quit = 1 : ret.l = #True
					Case #G_Password_Cancel
						Quit = 1 : ret.l = #False
				EndSelect
			Case #PB_Event_CloseWindow  ; If the user has pressed on the close button
				Quit = 1 : ret.l = #False
		EndSelect
	Until Quit = 1
	
	
	If ret = #True
		Key = GetGadgetText(#G_Password_Pass)
	EndIf
	CloseWindow(#W_PassWord)
	ProcedureReturn ret
EndProcedure

WindowPasswordLoop() 
Last edited by thyphoon on Wed Aug 06, 2008 7:48 am, edited 3 times in total.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Interesting.

Kind of hard to tell what kind of password aBcD60 is though.

cheers
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

you should implement an Enter function, not testing on every event.
when clicking on the stringgadget to focus it, you already get "too short" two times.
when you enter something then, you get a debug on every single keystroke.
additionally, when you already built up a requester, you should use it but not the debug window.

<offtopic>
the old joke that "penis" is too short works here...
</offtopic>
oh... and have a nice day.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 345
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

Some change in the code ...See First Post
  • -Correct Too Short info
    -Add switch text in toogle button "abc" to "***" and reverse
    -the password is tested only when eventype()=#PB_EventType_Change
rsts wrote:Interesting.

Kind of hard to tell what kind of password aBcD60 is though.

cheers
Yes ! may be i must test chara suite. :P If you have some code suggestion to add in the passwordStrength procedure to have a better analyse i'm ready :wink:
Kaeru Gaman wrote:you should implement an Enter function, not testing on every event.
Y make a little change I test only if the password change
Kaeru Gaman wrote: when clicking on the stringgadget to focus it, you already get "too short" two times.
The last change correct this bug
Kaeru Gaman wrote: when you enter something then, you get a debug on every single keystroke.

additionally, when you already built up a requester, you should use it but not the debug window.
yes it's a forget ! I correct it :P
Kaeru Gaman wrote: <offtopic>
the old joke that "penis" is too short works here...
</offtopic>

:lol: :lol:
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Post by techjunkie »

Nice! :D

but "123qwe" get a score of 34 (good)?!? Maybe include some intelligence where the keys are located on the keyboard? :wink:
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 345
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

techjunkie wrote:Nice! :D

but "123qwe" get a score of 34 (good)?!? Maybe include some intelligence where the keys are located on the keyboard? :wink:
yes it's a good suggestion. I don't know , how to do it but i add it in the next version :D
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Hmm - starts and ends - no window to be seen :?:
CherokeeStalker
User
User
Posts: 66
Joined: Fri Oct 17, 2003 2:42 am

Post by CherokeeStalker »

rsts wrote:Hmm - starts and ends - no window to be seen :?:

Code: Select all

#W_PassWord = 0

;Gadget
Enumeration
   #G_Password_Pass
    #G_Password_Toggle
    #G_Password_Check
    #G_Password_Pass_Txt
    #G_Password_Ok
    #G_Password_Cancel
EndEnumeration

Global Key.s

;********************
;Function
;********************

Procedure Match(exp.s, txt.s)
   If CreateRegularExpression(0, exp) And MatchRegularExpression(0, txt)
      ProcedureReturn #True
   Else
      ProcedureReturn #False
   EndIf
EndProcedure

Procedure.s DelRepetition(pLen.l, str.s)
   res.s = ""
   For i = 1 To Len(str)
      repeated = #False
      
      For j = 1 To pLen
         If Mid(Str, i, j) = Mid(Str, i + j, j)
            repeated = #True :
            i = i + j-1
         EndIf
      Next
      If repeated = #False
         res + Mid(str, i, 1)
      EndIf
      
   Next i
   ProcedureReturn res
EndProcedure

Procedure.l passwordStrength(password.s)
   ;Source:http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
   score.l = 0
   
   ;password < 4
   If (Len(password)<5)
      score-50
   EndIf
   
   ;//password == username
   ;If (password.toLowerCase()==username.toLowerCase()) Return badPass
   
   ;//password length
   score + Len(password)*4
   score + (Len(DelRepetition(1, password))-Len(password) )*1
   score + (Len(DelRepetition(2, password))-Len(password) )*1
   score + (Len(DelRepetition(3, password))-Len(password) )*1
   score + (Len(DelRepetition(4, password))-Len(password) )*1
   score + (Len(DelRepetition(5, password))-Len(password) )*1
   
   ;//password has 3 numbers
   If Match("(.*[0-9].*[0-9].*[0-9])", password) : score + 5 : EndIf
   
   ;//password has 2 sybols
   If Match("(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])", password) : score + 5 : EndIf
   
   ;//password has Upper And Lower chars
   If Match("([a-z].*[A-Z])|([A-Z].*[a-z])", password) : score + 10 : EndIf
   
   ;//password has number And chars
   If Match("([a-zA-Z])", password) And Match("([0-9])", password) : score + 15 : EndIf
   
   ;//password has number And symbol
   If Match("([!,@,#,$,%,^,&,*,?,_,~])", password) And Match("([0-9])", password) : score + 15 : EndIf
   
   ;//password has char And symbol
   If Match("([!,@,#,$,%,^,&,*,?,_,~])", password) And Match("([a-zA-Z])", password) : score + 15 : EndIf
   
   ;//password is just a nubers Or chars
   If match("^\w+$", password) Or match("^\d+$", password) : score-10 : EndIf
   
   ;//verifing 0 < score < 100
   ;if (score<0) : Debug "very Bad" : EndIf
   ;If (score>100) : Debug "Perfect" : EndIf
   ;If (score = 0 And score<34) : Debug " bad" : EndIf
   ;If (score = 34 And score<68) : Debug " good" : EndIf
   ;If (score = 68 And score<100) : Debug " strong" : EndIf
   ProcedureReturn score
EndProcedure

Procedure TestPassword(Gdt.l, Pass.s)
   Protected Score.l
   If IsGadget(Gdt)
      Score.l = passwordStrength(Pass)
      If (Score<-40) : SetGadgetText(Gdt, "Too short (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, #Red) : EndIf
      If (Score> = -40 And Score<0) : SetGadgetText(Gdt, "very Bad (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, #Red) : EndIf
      If (Score> = 0 And score<34) : SetGadgetText(Gdt, " bad (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, $0033FF) : EndIf
      If (Score> = 34 And score<68) : SetGadgetText(Gdt, " good (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, $006600) : EndIf
      If (Score> = 68 And score<100) : SetGadgetText(Gdt, " strong (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, $66FF66) : EndIf
      If (Score>100) : SetGadgetText(Gdt, "Perfect (" + Str(Score) + ")") : SetGadgetColor(Gdt, #PB_Gadget_BackColor, #Green) : EndIf
   EndIf
EndProcedure


;Gdt=Gadget who display password / GdtToggle= gadget who sitch password display / GdtCont= If Gdt is in a container gadget
Procedure TogglePassword(Gdt.l, GdtToggle.l, GdtCont.l = -1)
   Protected tmppass.s, tmpx.l, tmpy.l, tmpw.l, tmph.l
   tmppass.s = GetGadgetText(Gdt)
   tmpx = GadgetX(Gdt)
   tmpy = GadgetY(Gdt)
   tmpw = GadgetWidth(Gdt)
   tmph = GadgetHeight(Gdt)
   FreeGadget(Gdt)
   If GdtCont>-1
      OpenGadgetList(GdtCont)
   EndIf
   If GetGadgetState(GdtToggle) = 0
      StringGadget(Gdt, tmpx, tmpy, tmpw, tmph, "", #PB_String_Password)
      SetGadgetText(GdtToggle, "abc")
   Else
      StringGadget(Gdt, tmpx, tmpy, tmpw, tmph, "")
      SetGadgetText(GdtToggle, "***")
   EndIf
   If GdtCont>-1
      CloseGadgetList()
   EndIf
   SetGadgetText(Gdt, tmppass)
EndProcedure

;********************
;Windows
;********************
Procedure OpenWindowPassword()
   OpenWindow(#W_PassWord, 0, 0, 400, 250, "Password", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
   CreateGadgetList(WindowID(#W_PassWord))
   
   TextGadget(#G_Password_Pass_Txt, 10, 55, WindowWidth(#W_PassWord)-20, 20, "Your Master Password")
   StringGadget(#G_Password_Pass, 10, 80, WindowWidth(#W_PassWord)-60, 20, "", #PB_String_Password)
   TextGadget(#G_Password_Check, 10, 110, WindowWidth(#W_PassWord)-60, 20, "", #PB_Text_Center | #PB_Text_Border)
   ;SetGadgetAttribute(#G_Password_Pass, #PB_String_Password , 0) //ça n'existe pas pour l'instant dommage
   ButtonGadget(#G_Password_Toggle, WindowWidth(#W_PassWord)-40, 80, 40, 20, "abc", #PB_Button_Toggle)
   ButtonGadget(#G_Password_Ok, 10, WindowHeight(#W_PassWord)-30, 60, 20, "Ok")
   ButtonGadget(#G_Password_Cancel, WindowWidth(#W_PassWord)-70, WindowHeight(#W_PassWord)-30, 60, 20, "Cancel")
   
EndProcedure

Procedure CloseWindowPassword(W_Parent)
   DisableWindow(W_Parent, 0)
EndProcedure

Procedure WindowPasswordLoop()
   Protected EventID.l, Quit.b, ret.l
   OpenWindowPassword()
   Repeat
      EventID = WaitWindowEvent()
      Select(EventID)
         Case #PB_Event_Repaint
            ;DrawWindowHead(#W_Icon)
         Case #PB_Event_Menu
         Case #PB_Event_Gadget
            
            Select EventGadget()
               Case #G_Password_Toggle
                  TogglePassword(#G_Password_Pass, #G_Password_Toggle)
               Case #G_Password_Pass
                  If EventType() = #PB_EventType_Change
                     TestPassword(#G_Password_Check, GetGadgetText(#G_Password_Pass))
                  EndIf
               Case #G_Password_Ok
                  Quit = 1 : ret.l = #True
               Case #G_Password_Cancel
                  Quit = 1 : ret.l = #False
            EndSelect
         Case #PB_Event_CloseWindow  ; If the user has pressed on the close button
            Quit = 1 : ret.l = #False
      EndSelect
   Until Quit = 1
   
   
   If ret = #True
      Key = GetGadgetText(#G_Password_Pass)
   EndIf
   CloseWindow(#W_PassWord)
   ProcedureReturn ret
EndProcedure

WindowPasswordLoop(); < - - - - - - - - - - - - - - - added this line !
superadnim
Enthusiast
Enthusiast
Posts: 480
Joined: Thu Jul 27, 2006 4:06 am

Post by superadnim »

how is "HelloWorld" a safe password?

:lol: should I bash the keyboard and give up?
:?
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 345
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

@CherokeeStalker

Thanks for your answer ! yes I forget the last line.
rsts wrote:Hmm - starts and ends - no window to be seen :?:
Excuse me when i Copy the code i forget the last line .

Code: Select all

WindowPasswordLoop();
superadnim wrote:how is "HelloWorld" a safe password?
The engine is not perfect. May be i will add a dictionary with bad password...
All code suggestion to improve the AI is welcome :P
User avatar
pdwyer
Addict
Addict
Posts: 2813
Joined: Tue May 08, 2007 1:27 pm
Location: Chiba, Japan

Post by pdwyer »

"Hello World" would be better 8)

11 character password with upper case, lower case and symbols :wink:

:P :P :P :P

I haven't really heard of a pwd strength meter before, only complience with regards to complexity policy which "Password1" would normally pass provided it is dissimilar to the user name and x number of previous passwords.

Very subjective topic otherwise isn't it?
Paul Dwyer

“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
superadnim
Enthusiast
Enthusiast
Posts: 480
Joined: Thu Jul 27, 2006 4:06 am

Post by superadnim »

Oh :D I wasn't trying to say it's bad code or anything it just surprised me that HelloWorld had an "ok" score. yes using a dictionary would be ideal but you would have to use a hash list as to improve speed and whatnot :o

One idea: check for syllables (this will only work on so many spoken languages though).

If you want to go mad on this, try and convert from 1337 characters into normal text and process that as well, because most password generators are capable of doing this and much more. While this isn't a password generator, it should be aware of any text that resembles phrases, words, part of words, etc.

So if you check the syllables, you'll be able to find out whether there are possible words in the password or not. I think this would be faster than any dictionary search because you'll be moving almost no data at all from-to memory and the processing is kept to a minimum.

Using regexp here is OK but what if you decide to run such a routine against a user base of 50.000+ ?? regexp is only going to get you that far :?

:lol: should I bash the keyboard and give up?
:?
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Created a alternative, this does not use regexp. Is very simple. But hopefully a bit more picky. The score math is different.
There is no penalty for short, other than being told it's weak or horrible that is.

Why? Because all passwords stored or transmitted should be hashed. A password cracker will not be able to know if the password was "A" or "AgHH6547"#% %" So the more password diversity the better.

I never liked password limiters/checkers, those just aids the crackers by telling them what the passwords contain/what is accepted, and annoys the users. (you must have at least 1 uppercase letter, you must have at least 1 numberdigit etc) most people just slap a 1 at the end anyway when "forced" to.

Password strength meters on the other hand is something I love. It let's me choose what I want, but advises me on it's strength. :)

The GetPasswordStrength() procedure can be speed up by removing the 'sc' case and variables, special chars will then get lumped with the unknown/unicode ones, should not affect the score too much either.
benefit is getting rid of that huge specials Case line.

Some more speed mai be gained by moving the GetPasswordStrength() procedure's code into the TestPassword() procedure thus eliminating a procedure call.

I'm sure there are other improvements possible as well.

Code: Select all

#W_PassWord = 0

;Gadget
Enumeration
   #G_Password_Pass
    #G_Password_Toggle
    #G_Password_Check
    #G_Password_Pass_Txt
    #G_Password_Ok
    #G_Password_Cancel
EndEnumeration

Global Key.s

;********************
;Function
;********************


Procedure.l GetPasswordStrength(password$)
 Protected *char.character,endpos.l
 Protected result.l=0,len.l,lc.l=0,uc.l=0,nm.l=0,sp.l=0,sc.l=0,un.l=0
 *char=@password$
 len=Len(password$)
 If len>0
  endpos=(@password$+(len*SizeOf(character)))-SizeOf(character)
  Repeat
   Select *char\c
    Case 'a' To 'z' ;lowercase
     lc+1
    Case 'A' To 'Z' ;uppercase
     uc+1
    Case '0' To '9' ;numeric
     nm+1
    Case ' ' ;space
     sp+1
    Case ',','.','-','"',Asc("'"),'*','!','@',',#',',$',',%',',^',',&',',?','_','~','[',']','(',')','<','>',';',':','£','¤','/','\','{','}','=','+','`','´','¨','|','§' ;special
     sc+1
    Default ;unknown or unicode characters
     un+1
   EndSelect
   *char=*char+SizeOf(character)
  Until *char>endpos
  result=1*(lc+1)*(uc+1)*(nm+1)*(sp+1)*(sc+1)*(un+1)
 EndIf
 ProcedureReturn result
EndProcedure

Procedure.l TestPassword(gadget.l,password$)
 Protected text$,strength.l,bgcolor.l
 strength=GetPasswordStrength(password$)
 If strength<0 : strength=$7FFFFFFF : EndIf
 If strength=0
  text$="Fail"
  fgcolor=$FFFFFF
  bgcolor=$0000AA
 ElseIf strength<10
  text$="Horrible"
  fgcolor=$FFFFFF
  bgcolor=$3333AA
 ElseIf strength<25
  text$="Weak"
  fgcolor=$FFFFFF
  bgcolor=$6666AA
 ElseIf strength<50
  text$="OK"
  fgcolor=$FFFFFF
  bgcolor=$AA6633
 ElseIf strength<100
  text$="Good"
  fgcolor=$FFFFFF
  bgcolor=$AA6666
 ElseIf strength<500
  text$="Great"
  fgcolor=$FFFFFF
  bgcolor=$66AA66
 ElseIf strength<1000
  text$="Strong"
  fgcolor=$FFFFFF
  bgcolor=$33AA33
 Else
  text$="Very Strong"
  fgcolor=$FFFFFF
  bgcolor=$00AA00
 EndIf
 SetGadgetText(gadget, text$+" ("+Str(strength)+")")
 SetGadgetColor(gadget,#PB_Gadget_BackColor,bgcolor)
 SetGadgetColor(gadget,#PB_Gadget_FrontColor,fgcolor)
EndProcedure

;Gdt=Gadget who display password / GdtToggle= gadget who sitch password display / GdtCont= If Gdt is in a container gadget
Procedure TogglePassword(Gdt.l, GdtToggle.l, GdtCont.l = -1)
   Protected tmppass.s, tmpx.l, tmpy.l, tmpw.l, tmph.l
   tmppass.s = GetGadgetText(Gdt)
   tmpx = GadgetX(Gdt)
   tmpy = GadgetY(Gdt)
   tmpw = GadgetWidth(Gdt)
   tmph = GadgetHeight(Gdt)
   FreeGadget(Gdt)
   If GdtCont>-1
      OpenGadgetList(GdtCont)
   EndIf
   If GetGadgetState(GdtToggle) = 0
      StringGadget(Gdt, tmpx, tmpy, tmpw, tmph, "", #PB_String_Password)
      SetGadgetText(GdtToggle, "abc")
   Else
      StringGadget(Gdt, tmpx, tmpy, tmpw, tmph, "")
      SetGadgetText(GdtToggle, "***")
   EndIf
   If GdtCont>-1
      CloseGadgetList()
   EndIf
   SetGadgetText(Gdt, tmppass)
EndProcedure

;********************
;Windows
;********************
Procedure OpenWindowPassword()
   OpenWindow(#W_PassWord, 0, 0, 400, 250, "Password", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
   CreateGadgetList(WindowID(#W_PassWord))
   
   TextGadget(#G_Password_Pass_Txt, 10, 55, WindowWidth(#W_PassWord)-20, 20, "Your Master Password")
   StringGadget(#G_Password_Pass, 10, 80, WindowWidth(#W_PassWord)-60, 20, "", #PB_String_Password)
   TextGadget(#G_Password_Check, 10, 110, WindowWidth(#W_PassWord)-60, 20, "", #PB_Text_Center | #PB_Text_Border)
   ;SetGadgetAttribute(#G_Password_Pass, #PB_String_Password , 0) //ça n'existe pas pour l'instant dommage
   ButtonGadget(#G_Password_Toggle, WindowWidth(#W_PassWord)-40, 80, 40, 20, "abc", #PB_Button_Toggle)
   ButtonGadget(#G_Password_Ok, 10, WindowHeight(#W_PassWord)-30, 60, 20, "Ok")
   ButtonGadget(#G_Password_Cancel, WindowWidth(#W_PassWord)-70, WindowHeight(#W_PassWord)-30, 60, 20, "Cancel")
   
EndProcedure

Procedure CloseWindowPassword(W_Parent)
   DisableWindow(W_Parent, 0)
EndProcedure

Procedure WindowPasswordLoop()
   Protected EventID.l, Quit.b, ret.l
   OpenWindowPassword()
   Repeat
      EventID = WaitWindowEvent()
      Select(EventID)
         Case #PB_Event_Repaint
            ;DrawWindowHead(#W_Icon)
         Case #PB_Event_Menu
         Case #PB_Event_Gadget
            
            Select EventGadget()
               Case #G_Password_Toggle
                  TogglePassword(#G_Password_Pass, #G_Password_Toggle)
               Case #G_Password_Pass
                  If EventType() = #PB_EventType_Change
                     TestPassword(#G_Password_Check, GetGadgetText(#G_Password_Pass))
                  EndIf
               Case #G_Password_Ok
                  Quit = 1 : ret.l = #True
               Case #G_Password_Cancel
                  Quit = 1 : ret.l = #False
            EndSelect
         Case #PB_Event_CloseWindow  ; If the user has pressed on the close button
            Quit = 1 : ret.l = #False
      EndSelect
   Until Quit = 1
   
   
   If ret = #True
      Key = GetGadgetText(#G_Password_Pass)
   EndIf
   CloseWindow(#W_PassWord)
   ProcedureReturn ret
EndProcedure

WindowPasswordLoop()
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Try with these passwords to see how the scoring system works.

abcd
1234
Password
abcd1234
abCD 1234
abCD 1234 !
The milk fell behind the fridge!
This is a 7'th test!
1 in the Brown, 2 in the Pink!
Polarwolf
New User
New User
Posts: 9
Joined: Fri Jan 11, 2008 3:27 pm
Location: Germany

Post by Polarwolf »

Wow. I reach an interesting score with my board password.

Perfect (131)

Who can beat that without cheating? O.o
Post Reply