\myheading{Forgotten password}

\renewcommand{\LstStyle}{\ttfamily\footnotesize}

You forgot a password, but this is what you remember: there was a name of your parent, or wife, or one of children.
Also, someone's year of birth.
And one punctuation character, which are so recommended in passwords.
Can you enumerate all possible passwords?

\lstinputlisting[style=custompy,basicstyle=\LstStyle]{comb/password/pw1.py}

\begin{lstlisting}
jake1987!
jake!1987
1987jake!
1987!jake
!jake1987

...

1963emily,
1963,emily
,emily1963
,1963emily
\end{lstlisting}

( 936 of them in total )

But nested for's are not aesthetically pleasing.
They can be replaced with "cartesian product" operation:

\lstinputlisting[style=custompy,basicstyle=\LstStyle]{comb/password/pw2.py}

And this is a way to memorize it: the length of the final result equals to lengths of all input lists multiplied with each other
(like "product").

\lstinputlisting[style=custompy,basicstyle=\LstStyle]{comb/password/pw21.py}

\begin{lstlisting}
('jake', '1987', '!')
('jake', '1987', '@')
('jake', '1987', '#')
('jake', '1987', '$')
('jake', '1987', '%')
('jake', '1987', '&')
('jake', '1987', '*')

...

('emily', '1963', '*')
('emily', '1963', '-')
('emily', '1963', '=')
('emily', '1963', '_')
('emily', '1963', '+')
('emily', '1963', '.')
('emily', '1963', ',')
\end{lstlisting}

4*3*13=156, and this is a size of a list, to be permuted...

Now the new problem: some Latin characters may be uppercased, some are lowercased.
I'll add another "cartesian product" operation to alter a final string in all possible ways:

\lstinputlisting[style=custompy,basicstyle=\LstStyle]{comb/password/pw3.py}

\begin{lstlisting}
JAke1987!
JAkE1987!
JAKe1987!
JAKE1987!
jake!1987
jakE!1987
jaKe!1987
jaKE!1987

...

,1963eMIly
,1963eMIlY
,1963eMILy
,1963eMILY
,1963Emily
,1963EmilY
,1963EmiLy
\end{lstlisting}

( 56160 passwords )

Now leetspeak\footnote{\href{https://www.urbandictionary.com/define.php?term=leet\%20speak}{urbandictionary.com}}
This is somewhat popular only among youngsters, but still, this is what people of all age groups do:
replacing "o" with "0" in their passwords, "e" with "3", etc.
Let's add this as well:

\lstinputlisting[style=custompy,basicstyle=\LstStyle]{comb/password/pw4.py}

\begin{lstlisting}
jake1987!
jakE1987!
jak31987!
jaKe1987!
jaKE1987!
jaK31987!

...

,1963EM1lY
,1963EM1Ly
,1963EM1LY
,19633mily
,19633milY
,19633miLy
\end{lstlisting}

( 140400 passwords )

Obviously, you can't try all 140400 passwords on Facebook, Twitter or any other well-protected internet service.
But this is a peace of cake to brute-force them all on password protected RAR-archive or feed them to
John the Ripper, HashCat, Aircrack-ng, etc.

All the files: \MakeURL{\RepoPath/comb/password}.

\myhrule{}

Now let's use combinations from itertools Python package.

Let's say, you remember that your password has maybe your name, maybe name of your wife, your year of birth, or her,
and maybe couple of symbols like \verb|!|, \verb|$|, \verb|^|.

\begin{lstlisting}[style=custompy,basicstyle=\LstStyle]
import itertools

parts=["den", "xenia", "1979", "1985", "secret", "!", "$", "^"]

for i in range(1, 6): # 1..5
    for combination in itertools.combinations(parts, i):
        print "".join(combination)
\end{lstlisting}

Here we enumerate all combinations of given strings, 1-string combinations, then 2-, up to 5-string combinations.
No string can appear twice.

\begin{lstlisting}
...
denxenia1979
denxenia1985
denxeniasecret
denxenia!
denxenia$
denxenia^
den19791985
den1979secret
den1979!
...
xenia1985secret$^
xenia1985!$^
xeniasecret!$^
19791985secret!$
19791985secret!^
...
\end{lstlisting}

(218 passwords)

Now let's permute all string in all possible ways:

\begin{lstlisting}[style=custompy,basicstyle=\LstStyle]
import itertools

parts=["den", "xenia", "1979", "1985", "secret", "!", "$", "^"]

for i in range(1, 6): # 1..5
    for combination in itertools.combinations(parts, i):
        for permutation in itertools.permutations(list(combination)):
            print "".join(permutation)
\end{lstlisting}

\begin{lstlisting}
...
^den
xenia1979
1979xenia
xenia1985
1985xenia
xeniasecret
secretxenia
xenia!
!xenia
...
^!$1985secret
^!$secret1985
^$1985secret!
^$1985!secret
^$secret1985!
^$secret!1985
^$!1985secret
^$!secret1985
\end{lstlisting}

(8800 passwords)

And finally, let's alter all Latin characters in lower/uppercase ways and add leetspeek,
as I did before:

\begin{lstlisting}[style=custompy,basicstyle=\LstStyle]
import itertools, string

parts=["den", "xenia", "1979", "1985", "!", "$", "^"]

for i in range(1, 6): # 1..5
    for combination in itertools.combinations(parts, i):
        for permutation in itertools.permutations(list(combination)):
            s="".join(permutation)
            t=[]
            for char in s:
                if char.isalpha():
                    to_be_appended=[string.lower(char), string.upper(char)]
                    if char.lower()=='e':
                        to_be_appended.append('3')
                    elif char.lower()=='i':
                        to_be_appended.append('1')
                    elif char.lower()=='o':
                        to_be_appended.append('0')
                    t.append(to_be_appended)
                else:
                    t.append([char])
            for q in itertools.product(*t):
                print "".join(q)            
\end{lstlisting}

\begin{lstlisting}
...
dEnxenia
dEnxeniA
dEnxenIa
...
D3nx3N1a
D3nx3N1A
D3nXenia
D3nXeniA
D3nXenIa
...
^$1979!1985
^$19851979!
^$1985!1979
^$!19791985
^$!19851979
\end{lstlisting}
( 1,348,657 passwords )

Again, you can't try to crack remote server with so many attempts,
but this is really possible for password-protected archive, known hash, etc...

