3

Looking to implement an end user dialog that requires them to create their own password.

Must be 9 characters long. 1 char must be upper case, 1 must be lowercase, one must be a number, ['0'..'9'] and one must be from a set of 6 predefined ascii chars like so. ['!','#','%','&','*','@'].

Have this completed. and works. However, what I wanted to do to was provide visible verification using the onchange event to change the color of the edit box to green if all requirments where met or RED if not. Valdating for the 9 char length is easy enough however checking the 9 various chars to ensure there is at least 1 upper, 1 lower, 1 number and 1 of the predefined is proving a tad difficult. Can anyone help please? Thank you.

This is the code:

procedure TPasswordForm.edtPassword1Change(Sender: TObject);      
  begin
    if Length(edtPassword1.Text <> 9 then
       edtPassword1.Color := clRed
    else
       edtPassword1.Color := clLime;
  end;
Sebastian Proske
  • 8,255
  • 2
  • 28
  • 37
Jerry Mallett
  • 75
  • 1
  • 6
  • 2
    [Reminds me this](http://imgur.com/VqRuocP) :) No, seriously, [are you sure](https://xkcd.com/936/)? – Victoria Aug 26 '17 at 11:40
  • 1
    Was that a comment Victoria??? Confused for sure!!! – Jerry Mallett Aug 26 '17 at 11:43
  • @JerryMallett you could look for regexp to create something better. Anyway the documentation can help you. For example you could do `if (theNumber in ['0'..'9']) then` where `theNumber` is the number (a character) you are looking for. – Alberto Miola Aug 26 '17 at 11:46
  • Yes, it was. You've asked how to do X and I was trying to show you that Y might be better. If you're the one who implements authentication, consider removing those restrictions. – Victoria Aug 26 '17 at 11:46
  • Have you made any effort to implement your validation scheme? A programmer should be able to do this. – David Heffernan Aug 26 '17 at 11:46
  • Tried that but trying to test for the 4 required and the password length has not gone well. Been working on this for the past 3hours and have googled on various keywords and phrases and come up empty. as for regexp...Is that a component for Delphi. – Jerry Mallett Aug 26 '17 at 11:49
  • Ok, I'll write a validation function for you. What is your Delphi version? – Victoria Aug 26 '17 at 11:51
  • 1
    David, I would most definitly not label myself as a programmer. I'm a delphi dabbler, self taught and I get by with the odd push and help for various good people on forums like this....too old to be going back to school.... – Jerry Mallett Aug 26 '17 at 11:53
  • Thank you Victoria, using Delphi 2007 – Jerry Mallett Aug 26 '17 at 12:10
  • @Victoria - The comic is far from being accurate, see https://en.wikipedia.org/wiki/Dictionary_attack – Sertac Akyuz Aug 26 '17 at 15:29
  • @Sertac, https://www.theverge.com/2017/8/7/16107966/password-tips-bill-burr-regrets-advice-nits-cybersecurity. With restrictions mentioned in this question may people tend to use sort of `123456789aA!`. And you forgot adding salt (which makes dictionary attack difficult). – Victoria Aug 26 '17 at 15:50
  • @Victoria - That doesn't justify the suggested alternative. The article fails to even mention such a thing as a dictionary attack exists. That's what's being employed on passwords before brute force is attempted. Neither the comic nor the article is technical. – Sertac Akyuz Aug 26 '17 at 15:55
  • Don't misunderstand me, I'm not encouraging what's being criticized - a good dictionary covers common degenerations on words. A good password is a meaningless set of mixed characters/numbers/symbols having a sensible length.. – Sertac Akyuz Aug 26 '17 at 16:16
  • @Sertac, if you're scared from brute force attack at your service authentication, sanitize your service (e.g. block account after a number of unsuccessful attempts). If you're scared from guessing plain text password from a MITM obtained hash, add salt to the password. There's many ways to protect, so as many ways to attack. Adding char diversity may IMHO drive less experienced users to use kind of `123456789aA!` password (because it's easy to remember and they don't need to use another yellow sticky paper). Experienced users use random password storing it securely in a safe place. – Victoria Aug 26 '17 at 16:21
  • 2
    Complex password rules will usually not lead to more safe passwords, important is only a minimum length. People cannot remember tons of strong passwords, and such rules can interfere with good password schemes. People can get very inventive to bypass such rules, e.g. by using weak passwords like "Password-2017". Often you end up with weaker passwords instead of stronger ones. Recently NIST published an [official paper](https://pages.nist.gov/800-63-3/sp800-63b.html), advising against such rules, and against its former recommendations. – martinstoeckli Aug 27 '17 at 08:12

2 Answers2

7

For fixed char sets function might be quite simple. Note that it does not accept non-Latin chars.

function IsPasswordCrazy(const s: AnsiString): Boolean;
const
  C_Upcase = 1;
  C_Locase = 2;
  C_Digit = 4;
  C_SpecSym = 8;
  C_All = C_Upcase or C_Locase or C_Digit or C_SpecSym;
var
  i, keys: integer;
begin

  if Length(s) <> 9 then begin
    Result := False;
    Exit;
  end;

  keys := 0;
  for i := 1 to Length(s) do
    case s[i] of
      'A'..'Z': keys := keys or C_Upcase;
      'a'..'z': keys := keys or C_Locase;
      '0'..'9': keys := keys or C_Digit;
      '!','#','%','&','*','@': keys := keys or C_SpecSym;
    end;

  Result := keys = C_All;
end;
MBo
  • 77,366
  • 5
  • 53
  • 86
3

This could be achieved using Regular Expressions

Here is an example with error messages.

uses
  System.RegularExpressions;


function ValidatePassword(aPassword: String; var ErrorMessage: String): Boolean;
begin
  Result := false;
  ErrorMessage := '';

  if Length(aPassword) <> 9 then
  begin
    ErrorMessage := 'Password must be exactly 9 characters long';
    exit;
  end;

  if not TRegEx.IsMatch(aPassword, '[a-z]') then
  begin
    ErrorMessage := 'At least 1 character in the password must be lowercase';
    exit;
  end;

  if not TRegEx.IsMatch(aPassword, '[A-Z]') then
  begin
    ErrorMessage := 'At least 1 character in the password must be uppercase';
    exit;
  end;

  if not TRegEx.IsMatch(aPassword, '\d') then
  begin
    ErrorMessage := 'At least 1 character in the password must be a digit';
    exit;
  end;

  if not TRegEx.IsMatch(aPassword, '[!,#,%,&,*,@]') then
  begin
    ErrorMessage := 'At least 1 character in the password must be one of the following letters: !,#,%,&,*,@';
    exit;
  end;

  Result := True;
end;
Jens Borrisholt
  • 6,174
  • 1
  • 33
  • 67
  • Is `TRegEx` available in Delphi2007? – Fabrizio Aug 27 '17 at 09:23
  • Hi Guys, thanks for all the comments and sample code. Haven't been well lately hence the reason I'm only responding now. just getting back into it now so I'm off to digest these comments and code samples. As Arnie would say...I'll Be Back! – Jerry Mallett Sep 09 '17 at 09:42
  • @JerryMallett When? And keep in mind to choose one answer as correct. – AmigoJack Nov 06 '21 at 12:12
  • This is not valid regex to begin with and the code would count `,` as required character. Why do so many people use regex when not even understanding their basics? [Putting commas in classes is as wrong as](https://www.regular-expressions.info/charclass.html) escaping dots in there. – AmigoJack Nov 06 '21 at 12:18