• Good, modern password security is often considered either "too cumbersome" for users, or "too CPU intensive"; at this point, as far as I am aware, GPGPU hashing is only aware for those that write dedicated code; i.e. those doing cracking (security audits/legitimate activity and/or malicious activity and/or not intentionally malicious activity, etc.). Thus, crackers at this time have on the order of a thousand-fold hash speed advantage (i.e. about 15 years of password life) over most corporate password hashing capabilities. That's likely to continue until hashing makes it to CPU's, as most corporations aren't going to fork over the $$, power, and cooling budget for Tesla or other industrial GPGPU cards.

    The basic steps to take are:

    1) Determine how long you need this password to last

    a) Note that all the "you must change your password every N time units" rules fail for people who don't log in that often unless they're forced to completely re-register after

    b) Note that some data needs to be protected for N years for regulatory reasons

    c) Note that people are living longer lives; some information (particularly health care or sealed juvenile records) should be protected for at least an individual's entire lifespan.

    2) Determine the level of adversary you wish to handle

    3) Determine the current rates at which hashes are being cracked by on a given machine today, and then extrapolate that to the level of adversary.

    a) For example, as of late 2011, a single machine with 8 GPU's was recorded as cracking 15.7 billion (with a B) SHA-1 hashes every second. At $330/ea, that's $2,640 in video cards; being generous, that's perhaps $3500 per machine. If you wish to deal with a $10,000 budget adversary, assume 3 machines, or 47.1 billion SHA-1 hashes per second _today_. If you wish to deal with a $500,000 budget adversary, assume 2.3 Trillion SHA-1 hashes every second.

    4) Account for Moore's Law! If today's machine will take 147,000 years to crack the password, then realize that the advancement of technology, if we assume a doubling every 18 months, will crack the password in about 25 years - well within the lifetime of most users. Further, in about 35 years, that password will be cracked in less than a year by a far less well funded adversary.

    a) Rule of thumb: Expect your adversary to get 128 times faster every 10.5 years, or 16,384 times faster every 21 years.

    b) This is much more critical for encryption, particular for legally protected information in your jurisdiction!!! If someone makes a copy of your encrypted data... and then decrypts it in 25 years, that could still be a big deal (for instance, financial, health care, or sealed juvenile information).

    5) Having picked your hash (If possible, please use SHA512, SHA256, Whirlpool, one of the SHA3 finalists, your country's regulatory approved hash suites or, if you must, SHA1. DO NOT use MD5, or MD4), determine the balance between length, complexity, and number of PBKDF2 hashing iterations required to actually meet the requirements you determined.

    a) PBKDF2 (Password-Based Key Derivation Function, PKCS #5 2.0) is a specific algorithm for having multiple iterating hashes for generating a password; see the Wikipedia PBKDF2 link, IETF RFC2898 (PKCS #5 2.0)

    b) Microsoft .NET Framework provides Rfc2898DeriveBytes but only for SHA1 (very unfortunate)

    c) BouncyCastle also has a C# (linked) and Java library released under a modified MIT X11 license (lawfully free for commercial and noncommercial use) that has PBKDF2 functionality; a C# example discussion can be found on StackOverflow

    d) Yes, you need to use PBKDF2; don't fall into the trap of the two-key TripleDES specification, which combined three iterations of 56-bit DES and arrived at all of 80 bits of security due to a very technical mathematical property. Note that even three-key TripleDES combines three iterations of 56-bit DES at arrives at only 112 bits of security.

    6) Follow other normal rules - salt with a long (128 bit or more), random salt that's different for every password (can be stored in the clear; it's just a salt/nonce), use random IV's (Initialization Vectors) for encryption, also stored in the clear, etc.

    7) Always use Cryptographically sound random number generators (For .NET, I believe that is RNGCryptoServiceProvider), not the normal pseudorandom number generators.

    a) Why not? Well, a normal pseudorandom number generator inherently predictable; that's why with the same seed, we get the same results. For crypto purposes, we do not want predictable results.

    8) Hire a professional security consultant (or see if your current security vendor will) code review your security code; there are many, many easy mistakes to make.

    a) And the examples you see on the Internet typically make almost all of them, apparently being from the "If it doesn't crash, and my app functions like I expect, it's GOOD!" school of thought.

    9) And check to see if the passwords users propose have any chance at all of standing up to a hybrid dictionary attack. Users will choose "password" as their password, and if you say "Use upper case and lower case both", they'll choose "Password"; if you want a number also, you get "Password1", if you want symbols too, you get "Password1!", until you force them to change their password every 30 days, in which case you get "Password2!", "Password3!", and so on.

    a) None of which survive very well in an environment where an attacker with a single $3500 machine can try a ten million word dictionary, apply a rule to use lowercase, all uppercase, and uppercase the first letter and lowercase the rest, apply a rule to add every number from 0 to 999 after each word, and apply a rule to add one of the32 standard keyboard symbols to the end of that. This is 10,000,000 * 3 * 1001 * 33 = 990,990,000,000 possibilities (1001 and 33 because there's also the option of "don't use that rule"). This sounds like a lot... but at 15.7 billion hashes a second, if you applied only a single SHA1 hash to it, that takes only 64 seconds.

    Here's some very primitive code to run very basic password checks. It assumes a table of lowercase + number + symbol passwords (essentially, it assumes that the cracking rules will handle case combinations, and thus compares in a case-insensitive fashion). You'll need to modify this to fit your rules; right now it's based on the very standard "minimum 8 characters, at least three of Upper, Lower, Number, Symbol" rules, the less standard "14 or more is good!" rule, and the less standard "If _these_ hybrid dictionary rules find your password, imagine what a real attacker will use" rule. Note that many bad passwords will make it through; there's no provision for taking two words together, and the suffix rules are limited to "two symbol/three number/common year suffix", and prefix rules are barely even present.

    Password lists to start you off can be found by a Google search on "wordlist" - Darknet, Ob-security, Korelogic, Skullsecurity, the U.S. Census, and others have good lists, including (unabridged) dictionaries for various languages, name lists for various languages, Facebook name lists, themed lists (sports, music, movies, etc.), place names, leaked passwords others have seen and/or cracked (Gawker, Rockyou, etc.). Many cracking tools also come with dictionaries, including the Backtrack linux distribution. If you're going to look for these, keep your antivirus software up to date, try to stay on what appear to be major security, government, or educational sites and try to only download text files or compressed text files; take a look inside before decompressing.

    USE [YourDB]

    GO

    CREATE TABLE [dbo].[YourPasswordList_LowercaseOnly](

    [Password] [varchar](255) NOT NULL,

    CONSTRAINT [PK_YourPasswordList_LowercaseOnly] PRIMARY KEY CLUSTERED

    (

    [Password] ASC

    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]

    ) ON [PRIMARY]

    GO

    -- Fill [YourPasswordList_LowercaseOnly] from your favorite sources

    GO

    CREATE PROCEDURE [dbo].[YourNamingConvention_IsBadPassword]

    @Password [varchar](255),

    @Username [varchar](255) = NULL,

    @Firstname [varchar](255) = NULL,

    @Lastname [varchar](255) = NULL,

    @Email [varchar](255) = NULL,

    @IsBad [bit] OUTPUT,

    @Message [varchar](255) OUTPUT

    WITH EXECUTE AS CALLER

    AS

    /*

    DECLARE @IsBadOut BIT

    DECLARE @MessageOut VARCHAR(255)

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = '@Password123!!'

    ,@email = 'MyEmail@domain.tld'

    ,@firstname = 'John'

    ,@lastname = 'James'

    ,@username = 'Bob'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'J&áN>A-,ë4^¯j[#÷ŸÚQÈ«pzKÏÇßüÒxÐ'

    ,@email = 'Ancient@BonestrewnCrest.org'

    ,@firstname = 'Jane'

    ,@lastname = 'Adriel'

    ,@username = 'Carol'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'shrt3t'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'pa$$w0rd'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'pa$$w0rd2000'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'pa$$w0rd123'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'password1;'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'nevar, ky123'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = '}rhundrede805'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = '}rhundredeabc'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = '08/15/2011'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'Sep 15 2011 00:00:00'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = '08/15/2011aldsfjlasfj'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'use6rname1$'

    ,@username = 'use6rname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@username = 'usadsfADSFArname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@lastname = 'use6rname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@lastname = 'usadsfADSFArname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@firstname = 'use6rname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@firstname = 'usadsfADSFArname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@email = 'use6rname'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@email = 'use6rname@bob.com'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'QQQQuse6rname1$'

    ,@email = 'usadsfADSFArname@bob.com'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = '%8a1|0o|/|s2'

    ,@email = 'usadsfADSFArname@bob.com'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'P@ssword'

    ,@email = 'usadsfADSFArname@bob.com'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    EXEC YourDB.[dbo].[YourNamingConvention_IsBadPassword]

    @Password = 'vVozniak1'

    ,@email = 'usadsfADSFArname@bob.com'

    ,@IsBad = @IsBadOut OUTPUT

    ,@Message = @MessageOut OUTPUT

    SELECT @IsBadOut, @MessageOut

    */

    SET @IsBad = 0; -- default to good

    SET @Message = 'Acceptable, though 14 characters or more is better.'

    DECLARE @PWTrim VARCHAR(255);

    DECLARE @PWTrimLow VARCHAR(255);

    DECLARE @PWTrimLowLeftBut1 VARCHAR(255);

    DECLARE @PWTrimLowLeftBut2 VARCHAR(255);

    DECLARE @PWTrimLowLeftBut3Num VARCHAR(255);

    DECLARE @PWTrimLowLeftBut4Num VARCHAR(255);

    DECLARE @PWTrimLowRightBut1 VARCHAR(255);

    DECLARE @PWTrimLowRightBut1LeftBut1 VARCHAR(255);

    DECLARE @PWNoLetterNumber VARCHAR(255);

    DECLARE @PWLeetTempLow VARCHAR(255);

    DECLARE @PWLeetTempLowLeftBut1 VARCHAR(255);

    DECLARE @PWLeetTempLowLeftBut2 VARCHAR(255);

    DECLARE @PWLeetTempLowRightBut1 VARCHAR(255);

    DECLARE @PWLeetTempLowRightBut1LeftBut1 VARCHAR(255);

    DECLARE @PWLeetTempLowLeftBut3Num VARCHAR(255);

    DECLARE @PWLeetTempLowLeftBut4Num VARCHAR(255);

    DECLARE @HasUpper BIT;

    SET @HasUpper = 0

    DECLARE @HasLower BIT;

    SET @HasLower = 0

    DECLARE @HasNumber BIT;

    SET @HasNumber = 0

    DECLARE @HasSymbol BIT;

    SET @HasSymbol = 0

    SET @PWTrim = LTRIM(RTRIM(@Password));

    SET @PWTrimLow = LOWER(@PWTrim);

    IF LEN(@PWTrimLow) < 8

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This password is far too short. 8 characters is the minimum, though 14 or more characters is much better.'

    RETURN;

    END

    ELSE IF LEN(@PWTrimLow) >= 14

    SET @Message = 'Good!'

    SET @PWTrimLowLeftBut1 = LEFT(@PWTrimLow,LEN(@PWTrimLow)-1)

    SET @PWTrimLowLeftBut2 = LEFT(@PWTrimLow,LEN(@PWTrimLow)-2)

    IF ISNUMERIC(RIGHT(@PWTrimLow,3)+'0.0e0') = 1

    SET @PWTrimLowLeftBut3Num = LEFT(@PWTrimLow,LEN(@PWTrimLow)-3)

    IF ISNUMERIC(RIGHT(@PWTrimLow,4)+'0.0e0') = 1

    SET @PWTrimLowLeftBut4Num = LEFT(@PWTrimLow,LEN(@PWTrimLow)-4)

    SET @PWTrimLowRightBut1 = RIGHT(@PWTrimLow,LEN(@PWTrimLow)-1)

    SET @PWTrimLowRightBut1LeftBut1 = LEFT(@PWTrimLowRightBut1,LEN(@PWTrimLowRightBut1)-1)

    IF @PWTrim COLLATE Latin1_General_BIN LIKE '%[A-Z]%' COLLATE Latin1_General_BIN

    SET @HasUpper = 1;

    IF @PWTrim COLLATE Latin1_General_BIN LIKE '%[a-z]%' COLLATE Latin1_General_BIN

    SET @HasLower = 1;

    IF @PWTrim LIKE '%[0-9]%'

    SET @HasNumber = 1;

    SET @PWNoLetterNumber = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLow,'a',''),'b',''),'c',''),'d',''),'e',''),'f',''),'g',''),'h',''),'i',''),'j',''),'k',''),'l',''),'m',''),'n',''),'o',''),'p',''),'q',''),'r',''),'s',''),'t',''),'u',''),'v',''),'w',''),'x',''),'y',''),'z',''),'0',''),'1',''),'2',''),'3',''),'4',''),'5',''),'6',''),'7',''),'8',''),'9','')

    IF LEN(@PWNoLetterNumber) > 0

    SET @HasSymbol = 1;

    IF CAST(@HasUpper AS TINYINT) + CAST(@HasLower AS TINYINT) + CAST(@HasNumber AS TINYINT) + CAST(@HasSymbol AS TINYINT) < 3

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'Your password must contain at least 3 of the following: Upper case, Lower case, Numbers, and Symbols.';

    RETURN;

    END

    IF IsDate(@PWTrimLow) = 1

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a date; do not choose dates as passwords.';

    RETURN;

    END

    IF @PWTrimLow LIKE '%' + @Username + '%'

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'Do not have your username as part of your password.';

    RETURN;

    END

    IF @PWTrimLow LIKE '%' + @Firstname + '%'

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'Do not have your first name as part of your password.';

    RETURN;

    END

    IF @PWTrimLow LIKE '%' + @Lastname + '%'

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'Do not have your last name as part of your password.';

    RETURN;

    END

    IF @PWTrimLow LIKE '%' + @email + '%'

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'Do not have your email address as part of your password.';

    RETURN;

    END

    IF @PWTrimLow LIKE '%' + LEFT(@email,CHARINDEX('@',@email)-1) + '%'

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'Do not have your email address as part of your password.';

    RETURN;

    END

    -- It passes basic rules; now let's see if it or simple variations of it are common.

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLow)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password, and is in common cracking dictionaries.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLowLeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password plus a character, and is vulnerable to dictionary + suffix attacks.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLowRightBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password, and is vulnerable to prefix + dictionary attacks.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLowLeftBut2)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password plus two characters, and is vulnerable to dictionary + suffix attacks.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLowRightBut1LeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password plus a character, and is vulnerable to prefix + dictionary + suffix attacks.';

    RETURN;

    END

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    BEGIN --IF @PWTrimLowLeftBut3Num IS NOT NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password plus three numbers, and is vulnerable to dictionary + suffix attacks.';

    RETURN;

    END

    -- The last 3 are numbers or @; let's see if there's 4, and they're a common year!

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    IF RIGHT(@PWTrimLow,4) BETWEEN '1900' AND '2035'

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWTrimLowLeftBut4Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password plus a common year, and is vulnerable to dictionary + suffix attacks.';

    RETURN;

    END

    END --IF @PWTrimLowLeftBut3Num IS NOT NULL

    -- NOTE the Leet speak translations are very primitive, and will let a lot through.

    -- That said, they should catch a few of the most common single letter replacements, trivial replacements, and perhaps some complete replacements.

    -- Better than nothing; if this catches it, John the ripper or hashcat with a good ruleset will certainly catch it!

    -- First leet translation.

    SET @PWLeetTempLow = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLow,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    SET @PWLeetTempLowLeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    SET @PWLeetTempLowLeftBut2 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut2,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    SET @PWLeetTempLowRightBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    SET @PWLeetTempLowRightBut1LeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1LeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    SET @PWLeetTempLowLeftBut3Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut3Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    ELSE

    SET @PWLeetTempLowLeftBut3Num = NULL

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    SET @PWLeetTempLowLeftBut4Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut4Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i')

    ELSE

    SET @PWLeetTempLowLeftBut4Num = NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLow)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to common cracking dictionaries with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut2)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus two characters, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to prefix + dictionary attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1LeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to prefix + dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    BEGIN --IF @PWTrimLowLeftBut3Num IS NOT NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus three numbers, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    -- The last 3 are numbers or @; let's see if there's 4, and they're a common year!

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    IF RIGHT(@PWTrimLow,4) BETWEEN '1900' AND '2035'

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a common year, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    END --IF @PWTrimLowLeftBut3Num IS NOT NULL

    -- Second leet translation; | means l instead of i.

    SET @PWLeetTempLow = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLow,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    SET @PWLeetTempLowLeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    SET @PWLeetTempLowLeftBut2 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut2,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    SET @PWLeetTempLowRightBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    SET @PWLeetTempLowRightBut1LeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1LeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    SET @PWLeetTempLowLeftBut3Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut3Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    ELSE

    SET @PWLeetTempLowLeftBut3Num = NULL

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    SET @PWLeetTempLowLeftBut4Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut4Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l')

    ELSE

    SET @PWLeetTempLowLeftBut4Num = NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLow)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to common cracking dictionaries with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut2)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus two characters, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to prefix + dictionary attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1LeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to prefix + dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    BEGIN --IF @PWTrimLowLeftBut3Num IS NOT NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus three numbers, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    -- The last 3 are numbers or @; let's see if there's 4, and they're a common year!

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    IF RIGHT(@PWTrimLow,4) BETWEEN '1900' AND '2035'

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a common year, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    END --IF @PWTrimLowLeftBut3Num IS NOT NULL

    -- Third leet translation, vv means w

    SET @PWLeetTempLow = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLow,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    SET @PWLeetTempLowLeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    SET @PWLeetTempLowLeftBut2 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut2,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    SET @PWLeetTempLowRightBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    SET @PWLeetTempLowRightBut1LeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1LeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    SET @PWLeetTempLowLeftBut3Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut3Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    ELSE

    SET @PWLeetTempLowLeftBut3Num = NULL

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    SET @PWLeetTempLowLeftBut4Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut4Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','i'),'vv','w')

    ELSE

    SET @PWLeetTempLowLeftBut4Num = NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLow)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to common cracking dictionaries with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut2)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus two characters, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to prefix + dictionary attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1LeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to prefix + dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    BEGIN --IF @PWTrimLowLeftBut3Num IS NOT NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus three numbers, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    -- The last 3 are numbers or @; let's see if there's 4, and they're a common year!

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    IF RIGHT(@PWTrimLow,4) BETWEEN '1900' AND '2035'

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a common year, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    END --IF @PWTrimLowLeftBut3Num IS NOT NULL

    -- Fourth leet translation; | means l instead of i, and vv means w

    SET @PWLeetTempLow = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLow,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    SET @PWLeetTempLowLeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    SET @PWLeetTempLowLeftBut2 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut2,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    SET @PWLeetTempLowRightBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    SET @PWLeetTempLowRightBut1LeftBut1 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowRightBut1LeftBut1,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    SET @PWLeetTempLowLeftBut3Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut3Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    ELSE

    SET @PWLeetTempLowLeftBut3Num = NULL

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    SET @PWLeetTempLowLeftBut4Num = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLowLeftBut4Num,'@','a'),'/-\','a'),'4','a'),'8','b'),'|)','d'),'1)','d'),'3','e'),'|=','f'),'6','g'),'|-|','h'),'_/','j'),'|<','k'),'|\/|','m'),'/\/\','m'),'\/\/','w'),'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n'),'0','o'),'|>','p'),'&','q'),'|2','r'),'5','s'),'$','s'),'7','t'),'|_|','u'),'><','x'),'''/','y'),'\/','v'),'2','z'),'1','l'),'(','c'),'!','i'),'|','l'),'vv','w')

    ELSE

    SET @PWLeetTempLowLeftBut4Num = NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLow)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to common cracking dictionaries with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut2)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus two characters, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution, and is vulnerable to prefix + dictionary attacks with l337 translation rules.';

    RETURN;

    END

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowRightBut1LeftBut1)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a character plus a well known password with a simple leet speak (l337 speak) substitution plus a character, and is vulnerable to prefix + dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    IF @PWTrimLowLeftBut3Num IS NOT NULL

    BEGIN --IF @PWTrimLowLeftBut3Num IS NOT NULL

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus three numbers, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    -- The last 3 are numbers or @; let's see if there's 4, and they're a common year!

    IF @PWTrimLowLeftBut4Num IS NOT NULL

    IF RIGHT(@PWTrimLow,4) BETWEEN '1900' AND '2035'

    IF EXISTS(SELECT * FROM YourDB.dbo.YourPasswordList_LowercaseOnly WITH (nolock) WHERE Password = @PWLeetTempLowLeftBut3Num)

    BEGIN

    SET @IsBad = 1;

    SET @Message = 'This is a well known password with a simple leet speak (l337 speak) substitution plus a common year, and is vulnerable to dictionary + suffix attacks with l337 translation rules.';

    RETURN;

    END

    END --IF @PWTrimLowLeftBut3Num IS NOT NULL

    /*

    First Leet translation:

    REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PWTrimLow

    ,'@','a'),'/-\','a'),'4','a')

    ,'8','b')

    ,'|)','d'),'1)','d')

    ,'3','e')

    ,'|=','f')

    ,'6','g')

    ,'|-|','h')

    ,'_/','j')

    ,'|<','k')

    ,'|\/|','m'),'/\/\','m')

    ,'\/\/','w')

    ,'/\/','n'),'|\|','n'),'|/|','n'),'1\1','n')

    ,'0','o')

    ,'|>','p')

    ,'&','q')

    ,'|2','r')

    ,'5','s'),'$','s')

    ,'7','t')

    ,'|_|','u')

    ,'><','x')

    ,'''/','y')

    ,'\/','v')

    ,'2','z')

    ,'1','l')

    ,'(','c')

    ,'!','i'),'|','i')

    Multiuse:

    | i l

    Ordering:

    /\/ - m inside w inside n inside v

    */

    GO

    P.S. Failing to account for Moore's Law is the #2 failing I've seen in most password strength estimates. Failing to account for hybrid dictionary + rule attacks is, of course, the #1 failing ("Password123#" - upper case, lower case, numbers, symbols, 12 characters long... and almost as pathetic a password as you'll ever see, since Password123 is itself in most cracking dictionaries, and adding a character at the end is one of the first rules you'll see).

    P.P.S. For a brief example of a small variety of what hybrid dictionary attacks can do, see the Hashcat Wiki rule_based_attack page. Note there are available rulesets for "keywalking" as well! Note that the Hashcat tools are only free for noncommercial use; for commercial use, please contact the author for permission.

    P.P.P.S. Even leaving aside hybrid dictionary attacks, and assuming a user uses a purely random password (a good generator, rolling dice, etc.), for pure brute force, here are some rough guesses based on Moore's Law/computer power doubling every 18 months; these illustrate the premise that overall keyspace (number of possible characters^length) trumps all else, though number of iterations can provide a good buffer in the short term:

    8 char, Upper/Lower/Number, 1xSHA1, 100x$3500 machine: 3 minutes

    8 char, Upper/Lower/Number, 1xSHA1, $3500 machine: 4 hours

    8 char, Upper/Lower/Number, 32768xSHA1, $3500 machine: 5 years

    8 char, Upper/Lower/Number, 262144xSHA1, $3500 machine: 10 years

    10 char, Upper/Lower/Number, 1xSHA1, 100x$3500 machine: 6 days

    10 char, Upper/Lower/Number, 1xSHA1, $3500 machine: less than 2 years

    10 char, Upper/Lower/Number, 32768xSHA1, $3500 machine: 23 years

    10 char, Upper/Lower/Number, 262144xSHA1, $3500 machine: 28 years

    14 char, Upper/Lower/Number, 1xSHA1, 100x$3500 machine: 26 years

    14 char, Upper/Lower/Number, 1xSHA1, $3500 machine: 36 years

    14 char, Upper/Lower/Number, 32768xSHA1, $3500 machine: 59 years

    14 char, Upper/Lower/Number, 262144xSHA1, $3500 machine: 63 years

    32 char, Upper/Lower/Number, 1xSHA1, 100x$3500 machine: 187 years

    32 char, Upper/Lower/Number, 1xSHA1, $3500 machine: 197 years

    32 char, Upper/Lower/Number, 32768xSHA1, $3500 machine: 220 years

    32 char, Upper/Lower/Number, 262144xSHA1, $3500 machine: 224 years

    128 char, Upper/Lower/Number, 1xSHA1, 100x$3500 machine: 1045 years

    128 char, Upper/Lower/Number, 1xSHA1, $3500 machine: 1054 years

    8 char, Upper/Lower/Number/Parts of Printable Extended ASCII (total 152 possibilities per character), 1xSHA1, $3500 machine: 6 months

    10 char, Upper/Lower/Number/Parts of Printable Extended ASCII (total 152 possibilities per character), 1xSHA1, $3500 machine: 20 years

    14 char, Upper/Lower/Number/Parts of Printable Extended ASCII (total 152 possibilities per character), 1xSHA1, $3500 machine: 63 years

    NOTE: Upper/Lower/Number was chosen because A) people tend to prefer numbers to symbols when given the choice, B) most people choose from less than 10 symbols most of the time, even when they use symbols, and C) Various and sundry software has various and sundry requirements for various and sundry symbols, some require escaping ', some require escaping ", some require escaping [], some require escaping {}, and almost no software properly escapes any of these.

    P.P.P.P.S. If anyone would like to improve the l337 speak translation rules in the code above, please feel free to do so! The current copy/paste of the section once for every l337 speak variant is a horrifically bad way of implementing this. Any other improvements would also be welcome.