The timed InputRequester was tricky due to my typos and having to debug WITHOUT netmaestro's Messaging tool

If only I saw that earlier...

Code: Select all
; COMPILER OPTIONS:
; [x] Use Compiler: PureBasic 5.00 (x86)
; [ ] Use Icon:
; [ ] Enable inline ASM support
; [±] Create unicode executable
; [ ] Create threadsafe executable
; [ ] Enable OnError lines support
; [ ] Enable XP skin support
; [ ] Request Administrator mode for Windows Vista
; [ ] Request User mode for Windows Vista (no virtualization)
; Library Subsystem:
; Executable Format: Windows ;|Console|Shared DLL
; CPU: All ;|Dynamic|w/MMX|w/3DNOW|w/SSE|w/SSE2
; File Format: UTF-8
EnableExplicit
#SP$ = Chr(32)
#SPC = 32 ; " " ;#SP = 32 ; " " #SP fails???
Procedure.s SF_Encrypt_AESB64(s$, Key$, nKeyBits.i=256, *AESinit.Integer=0)
; REV: 121124, skywalk
; modified from Blue(Guy LeBleu), 111127
; Ascii or Unicode
; WARNING: AESEncoding can add Nulls to result, so cannot view with PeekS()
; Must convert AESresult to Base64$ for simple viewing.
; Also, if a result is stored in Ascii it cannot be decrypted with Unicode.
; Keep encryption data in same format!
; *AESinitvector accepts 16 bytes.
Protected.i n = StringByteLength(s$) + SizeOf(Character) ; include null terminator
If nKeyBits >= 256
nKeyBits = 256
ElseIf nKeyBits >= 192
nKeyBits = 192
Else
nKeyBits = 128
EndIf
If n < nKeyBits / 8
n = nKeyBits / 8 ; minimum size required by AES encoding
EndIf
Protected.i *AES = AllocateMemory(n) ; buffer for binary encrypted result
If *AES
Key$ = LSet(Key$, nKeyBits/8, #SP$) ; Force Key$ to correct size.
If *AESinit
AESEncoder(@s$, *AES, n, @Key$, nKeyBits, *AESinit, #PB_Cipher_CBC)
Else
AESEncoder(@s$, *AES, n, @Key$, nKeyBits, 0, #PB_Cipher_ECB)
EndIf
; convert AES$ to Base64 Ascii string
Protected.i n64 = n * 1.5 ; coding space for Base64 = 150%
If n64 < 64
n64 = 64 ; minimum required
EndIf
s$ = Space(n64) ; Reusing s$ variable = B64$
Base64Encoder(*AES, n, @s$, n64)
FreeMemory(*AES)
Else
s$ = #NULL$
EndIf
ProcedureReturn s$
EndProcedure
Procedure.s SF_Decrypt_AESB64(AESB64$, Key$, nKeyBits.i=256, *AESinit.Integer=0)
; REV: 121124, skywalk
; modified from Blue(Guy LeBleu), 111127
; Ascii or Unicode
; To rebuild AES encrypted block from a B64 string,
; you must know exact size of original AES encrypted buffer.
; WARNING: AESEncoding can add Nulls to result, so cannot view with PeekS()
; Must convert AESresult to Base64$ for simple viewing.
; Also, if a result is stored in Ascii it cannot be decrypted with Unicode.
; Keep encryption data in same format!
; *AESinitvector accepts 16 bytes.
Protected.i nAESB64 = StringByteLength(AESB64$)
Protected.i *AES = AllocateMemory(nAESB64)
If *AES
If nKeyBits >= 256
nKeyBits = 256
ElseIf nKeyBits >= 192
nKeyBits = 192
Else
nKeyBits = 128
EndIf
Base64Decoder(@AESB64$, nAESB64, *AES, nAESB64)
; Decrypt AES buffer to recover original expression
; Calculate nBytes in AES cipher from nBytes in Base64 string
; since each block of 4 base64 bytes represents 3 encrypted AES bytes,
; except for last one, which may end with padding characters.
; count number of padding bytes and subtract from final count.
; nAESbytes = lenB64String / 4 * 3 - n_fill_bytes
Protected.i *B64 = @AESB64$
Protected.i nAES = StringByteLength(AESB64$)
*B64 + nAES ; move pointer to last byte of string
nAES / 4 * 3 ; 3 AES bytes for each 4 Base64 bytes
If PeekB(*B64 - 2) = #SPC
nAES - 2
ElseIf PeekB(*B64 - 1) = #SPC
nAES - 1
EndIf
AESB64$ = Space(nAES) ; Reusing AESB64$ variable = s$
Key$ = LSet(Key$, nKeyBits/8, #SP$) ; Force Key$ to correct size.
If *AESinit
AESDecoder(*AES, @AESB64$, nAES, @Key$, nKeyBits, *AESinit, #PB_Cipher_CBC)
Else
AESDecoder(*AES, @AESB64$, nAES, @Key$, nKeyBits, 0, #PB_Cipher_ECB)
EndIf
FreeMemory(*AES)
Else
AESB64$ = #NULL$
EndIf
ProcedureReturn AESB64$
EndProcedure
#gui_TimerPSWDCHAR = 5555 ; Arbitrary number
#gui_TimerPSWDTMO = 10000 ; Timeout(ms), Change to ~15000 after debugging
Procedure gui_InputRequesterPSWD_CB(hW.i, Msg.i, idEvent.i, Time.i)
; REV: 121126, skywalk
Protected.s wT$ = Space(#MAX_PATH)
GetWindowText_(hW, @wT$, #MAX_PATH)
Protected.i hW_IRQ = FindWindow_("InputRequester", wT$)
If idEvent = #gui_TimerPSWDCHAR
Protected.i hW_Edit = FindWindowEx_(hW_IRQ, 0, "Edit", #NULL$)
;SendMessage_(hW_Edit, #WM_SETTEXT, 0, "You did not enter a password before timing out!")
SendMessage_(hW_Edit, #EM_SETPASSWORDCHAR, '*', 0)
SendMessage_(hW_Edit, #EM_SETSEL, 0, -1)
KillTimer_(hW, idEvent)
; Set new Timer w/Password prompt limit = #gui_TimerPSWDTMO msec
SetTimer_(hW, #gui_TimerPSWDTMO, #gui_TimerPSWDTMO, @gui_InputRequesterPSWD_CB())
ElseIf idEvent = #gui_TimerPSWDTMO
Protected.i hW_BTN = FindWindowEx_(hW_IRQ, 0, "Button", "OK") ; Must explicitly search for "OK"!
; FindWindowEx_(hW_IRQ, 0, "Button", #NULL$) ; Using Null$ or "" Fails! :(
; Choose your method to proceed once timeout occurs.
; Sendkeys [ESCAPE] = CANCEL
;keybd_event_(#VK_ESCAPE,0,0,0)
;keybd_event_(#VK_ESCAPE,0,#KEYEVENTF_KEYUP,0)
; Sendkeys [ENTER] = Full or partial capture of Password entered so far...
;keybd_event_(#VK_RETURN,0,0,0)
;keybd_event_(#VK_RETURN,0,#KEYEVENTF_KEYUP,0)
; SendClick [BM_CLICK] = Full or partial capture of Password entered so far...
SendMessage_(hW_BTN, #BM_CLICK, 0, 0)
KillTimer_(hW, idEvent)
EndIf
EndProcedure
Procedure.s gui_InputRequesterPSWD(wID, Prompt$="Enter Password", Def$=#NULL$)
; REV: 121126, skywalk
SetTimer_(WindowID(wID), #gui_TimerPSWDCHAR, 10, @gui_InputRequesterPSWD_CB())
ProcedureReturn InputRequester(GetWindowTitle(wID), Prompt$, Def$)
EndProcedure
#AESkey = 2
#AESinit = 4
#pwdYOU = 6
#pwdEncrypt = 8
#pwdDecrypt = 10
#pwdREAL = 12
If OpenWindow(0,0,0,400,400,"Password Prompt...",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
Define.s pwd$, key$ = "MYSUPERSECRETKEY", AESinit$ = "MYSUPERSECRETINITVECTOR"
Define.s pwdEncrypt$
Define.s pwdDecrypt$
Define.s pwdREAL$ = "PB5"
Define.i ht = 20, wd = 380, y = 10
ButtonGadget(0, wd/1.5+10, 10+(ht+y)*4, 100, 25, "Password Prompt")
TextGadget (1, 75,10+(ht+y)*0,wd,ht," -- AES KEY (length depends on nKeyBits) -- ")
StringGadget(#AESkey, 5,5+(ht+y)*1,wd,ht,key$)
TextGadget (3, 75,10+(ht+y)*2,wd,ht," -- AES InitVector (only 16 bytes used) -- ")
StringGadget(#AESinit, 5,5+(ht+y)*3,wd,ht,AESinit$)
TextGadget (5, 75,10+(ht+y)*4,wd,ht," -- Password You Entered -- ")
StringGadget(#pwdYOU, 5,5+(ht+y)*5,wd/1.5,ht,"")
TextGadget (7, 75,10+(ht+y)*6,wd,ht," -- AES256+BASE64 Encrypted Password -- ")
StringGadget(#pwdEncrypt, 5,5+(ht+y)*7,wd,ht,"")
TextGadget (9, 75,10+(ht+y)*8,wd,ht," -- AES256+BASE64 Encrypted Password -> Unencrypted -- ")
StringGadget(#pwdDecrypt,5,5+(ht+y)*9,wd/1.5,ht,"")
TextGadget (11, 75,10+(ht+y)*11,wd,ht," -- Password To Match -- ")
StringGadget(#pwdREAL,5,5+(ht+y)*12,wd/1.5,ht,pwdREAL$)
SetGadgetColor(#AESkey, #PB_Gadget_BackColor, #Yellow)
SetGadgetColor(#AESinit, #PB_Gadget_BackColor, #Yellow)
SetGadgetColor(#pwdYOU, #PB_Gadget_BackColor, #Yellow)
Define.i evWW
Repeat
evWW = WaitWindowEvent()
Select evWW
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
If EventGadget() = 0
pwd$ = gui_InputRequesterPSWD(0, "Enter Password: " + Str(#gui_TimerPSWDTMO/1000) + " second time limit!", "You did not enter a password before timing out!")
key$ = GetGadgetText(#AESkey)
AESinit$ = GetGadgetText(#AESinit)
SetGadgetText(#pwdYOU, pwd$)
pwdEncrypt$ = SF_Encrypt_AESB64(pwd$, key$, 256, @AESinit$)
SetGadgetText(#pwdEncrypt, pwdEncrypt$)
pwdDecrypt$ = SF_Decrypt_AESB64(pwdEncrypt$, key$, 256, @AESinit$)
SetGadgetText(#pwdDecrypt, pwdDecrypt$)
pwdREAL$ = GetGadgetText(#pwdREAL)
If pwdREAL$ = pwdDecrypt$
SetGadgetColor(#pwdDecrypt, #PB_Gadget_BackColor, #Green)
SetGadgetColor(#pwdREAL, #PB_Gadget_BackColor, #Green)
Else
SetGadgetColor(#pwdDecrypt, #PB_Gadget_BackColor, RGB(241, 77, 77))
SetGadgetColor(#pwdREAL, #PB_Gadget_BackColor, RGB(241, 77, 77))
EndIf
EndIf
EndSelect
ForEver
EndIf