Je veux un mot de passe qui ne scintille pas, alors j'utilise python pour créer un générateur de mot de passe qui spécifie un modèle.
ppwgen.py
#!/usr/bin/env python
flag_debug = False
flag_verbose = False
flag_syntax = False
def debug(msg):
    if flag_debug:
        print(msg)
def verbose(msg):
    if flag_verbose:
        print(msg)
def import_random():
    try:
        from Crypto.Random import random
        verbose('import Crypto.Random')
        return random
    except ImportError:
        pass
    try:
        import secrets
        verbose('import secrets')
        return secrets
    except ImportError:
        pass
    import random
    verbose('import random')
    return random
def charset_(r, x=''):
    s = ''
    for c in r:
        c = chr(c)
        if c not in x:
            s = s + c
    return s
def charset(s, x=''):
    r = ''
    while len(s) >= 3:
        if s[1] != '-':
            break
        cs = ord(s[0])
        ce = ord(s[2])
        r = r + charset_(range(cs, ce+1), x)
        s = s[3:]
    for c in s:
        if c not in x:
            r = r + c
    return r
def isescape(c):
    return (len(c) > 1) and (c[0] == '\\')
def unescape(c):
    if isescape(c):
        return c[1:]
    return c
class InvalidPattern(Exception):
    def __init__(self):
        Exception.__init__(self)
class PatIter:
    def __init__(self, pat):
        self.pos = 0
        s = []
        for c in list(pat):
            if len(s) and s[-1] == '\\':
                s[-1] = s[-1] + c
            else:
                s.append(c)
        if len(s) and s[-1] == '\\':
            if flag_syntax:
                raise InvalidPattern()
            s = s[:-1]
        self.pat = s
    def __iter__(self):
        return self
    def __next__(self):
        return self.next()
    def next(self):
        p = self.pos
        if p >= len(self.pat):
            raise StopIteration()
        self.pos = p + 1
        return self.pat[p]
    def rewind(self):
        self.pos = self.pos - 1
        return self
class Generator:
    def __init__(self, data):
        self.data = data
    def generate(self, random):
        s = self.data
        if type(s) == str:
            return random.choice(s)
        if type(s) == tuple:
            n = s[0]
            s = [s[1]]
        elif type(s) == list:
            n = 1
        else:
            raise Exception("Bug!")
        r = ''
        for i in range(n):
            for g in s:
                r = r + g.generate(random)
        return r
PATTERN_MAP = {
    'b': '01',
    'o': '01234567',
    'd': charset('0-9'),
    'X': charset('0-9A-F'),
    'x': charset('0-9a-f'),
    'A': charset('A-Za-z'),
    'C': charset('A-Z'),
    'c': charset('a-z'),
    'B': 'AEIOUaeiou',
    'V': 'AEIOU',
    'v': 'aeiou',
    'D': charset('A-Za-z', 'AEIUOaeiou'),
    'Q': charset('A-Z', 'AEIOU'),
    'q': charset('a-z', 'aeiou'),
    'Y': charset('0-9A-Za-z'),
    'Z': charset('0-9A-Z'),
    'z': charset('0-9a-z'),
    'W': charset('0-9A-Za-z_'),
    'L': charset('0-9A-Z'),
    'l': charset('0-9a-z'),
    '%': '%',
}
def check_not_close(c, q):
    return ((c is None) or (c != q)) and flag_syntax
class CustomPasswordGenerator:
    def __init__(self, pattern):
        ptr = PatIter(pattern)
        r = []
        for c in ptr:
            if c != '%':
                g = Generator(unescape(c))
            else:
                g = self.parse_pattern(ptr, False)
            if g != None:
                r.append(g)
        self.generator = Generator(r)
    def parse_pattern(self, ptr, nest):
        n = None
        c = None
        for c in ptr:
            if not c.isdigit():
                break
            if n is None:
                n = 0
            n = (n * 10) + int(c, 10)
        if n is None:
            n = 1
        if c is None:
            if flag_syntax:
                raise InvalidPattern()
            return None
        if c in PATTERN_MAP:
            return Generator((n, Generator(PATTERN_MAP[c])))
        if c == '{':
            return self.parse_subpat(ptr, n)
        if c == '[':
            return self.parse_charset(ptr, n)
        if isescape(c):
            c = unescape(c)
        elif (not nest) or (c in ']}'):
            raise InvalidPattern()
        return Generator((n, Generator(c)))
    def parse_subpat(self, ptr, rep):
        r = []
        c = None
        for c in ptr:
            if c == '}':
                break
            g = self.parse_pattern(ptr.rewind(), True)
            if g != None:
                r.append(g)
        if check_not_close(c, '}'):
            raise InvalidPattern()
        return Generator((rep, Generator(r)))
    def parse_charset(self, ptr, rep):
        r = []
        s = []
        c = None
        for c in ptr:
            if c == ']':
                break
            if len(s) < 2:
                s.append(c)
                continue
            a = unescape(s[0])
            if s[-1] != '-':
                r.append(a)
                s = s[1:]
                s.append(c)
                continue
            b = unescape(c)
            r.append(charset_(range(ord(a), ord(b)+1)))
            s = []
        if check_not_close(c, ']'):
            raise InvalidPattern()
        for a in s:
            r.append(unescape(a))
        return Generator((rep, Generator(''.join(r))))
    def generate(self, rnd=None, length=0):
        if rnd is None:
            rnd = import_random()
        pw = self.generator.generate(rnd)
        if length == 0:
            return pw
        while length > len(pw):
            pw = pw + self.generator.generate(rnd)
        return pw[:length]
def main():
    import argparse
    global flag_debug
    global flag_verbose
    global flag_syntax
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--debug', action='store_true', default=False)
    parser.add_argument('-v', '--verbose', action='store_true', default=False)
    parser.add_argument('-l', '--length', type=int, default=0)
    parser.add_argument('-U', '--upper', action='store_true', default=False)
    parser.add_argument('-L', '--lower', action='store_true', default=False)
    parser.add_argument('-n', '--count', type=int, default=0)
    parser.add_argument('-p', '--syntax', action='store_true', default=False)
    parser.add_argument('pattern', type=str, default='%l')
    args = parser.parse_args()
    flag_debug = args.debug
    flag_verbose = args.verbose or flag_debug
    flag_syntax = args.syntax
    converter = str
    if args.upper:
        converter = str.upper
    if args.lower:
        converter = str.lower
    pattern = args.pattern
    gen_length = args.length
    gen_count = args.count
    if gen_count == 0:
        gen_count = {False: 20, True: 2}[flag_debug]
    verbose('pattern = \'%s\'' % pattern)
    verbose('length = %d' % gen_length)
    verbose('count = %d' % gen_count)
    if flag_debug:
        verbose('PATTERN_MAP')
        for k in sorted(PATTERN_MAP):
            verbose('  \'%s\' : \'%s\'' % (k, PATTERN_MAP[k]))
        verbose('')
    try:
        gen = CustomPasswordGenerator(pattern)
    except InvalidPattern:
        print('invalid pattern: \'%s\'' % pattern)
        return
    rnd = import_random()
    fmt = '%' + str(len(str(gen_count))) + 'd: %s'
    for i in range(gen_count):
        print(fmt % (i+1, converter(gen.generate(rnd, gen_length))))
if __name__ == '__main__':
    main()
Décrivez le modèle à générer dans le style de format de langage C.
Immédiatement après le caractère% se trouve le caractère sélectionné par le nombre aléatoire.
| Prescripteur | type | Remarques | 
|---|---|---|
| b | Nombre binaire | [01] | 
| o | 8 base | [0-7] | 
| d | Nombres | [0-9] | 
| X | Chapiteau hexagonal | [0-9A-F] | 
| X | Minuscules hexagonales | [0-9a-f] | 
| A | Lettres anglaises | [A-Za-z] | 
| C | Capitale anglaise | [A-Z] | 
| c | Alphabet | [A-Z] | 
| B | Voyelle anglaise | [AEIOUaeiou] | 
| V | Voyelle anglaise(Gros) | [AEIOU] | 
| v | Voyelle anglaise(petit) | [aeiou] | 
| D | Son Eiko | [AEIOUaeiuo]à l'exception de[A-Za-z] | 
| Q | Son Eiko(Gros) | [AEIOU]à l'exception de[A-Z] | 
| q | Son Eiko(petit) | [AEIOU]à l'exception de[A-Z] | 
| Y | Alphabet | [0-9A-Za-z] | 
| Z | Alphabet(Gros) | [0-9A-Z] | 
| z | Alphabet(petit) | [0-9a-z] | 
| W | Caractère d'étiquette | [0-9A-Za-z_] | 
| L | Caractère d'étiquette(Gros) | [0-9A-Z_] | 
| l | Caractère d'étiquette(petit) | [0-9a-z_] | 
Exemple d'organisation des prescripteurs
$ python ppwgen.py -n 5 'qiita-%d%X%x%x%A%C%c%c%B%V%v%D%Q%q%Y%Z%z%W%L%l'
1: qiita-2D1cHSuhIEotMrdXh53r
2: qiita-2454ZXzlOIeXHc9GpD3n
3: qiita-2481ZFxhOUeZGjjHoP5y
4: qiita-7BffcNydeEaGZnUMyDUe
5: qiita-52f5nZqtAAiWTbGTphHj
Le nombre immédiatement après le caractère% est le nombre de caractères sélectionnés par le nombre aléatoire. Spécificateur% [numérique] C'est sous la forme de. Par exemple, «% 3d» sera un nombre à 3 chiffres.
$ python ppwgen.py -n 5 'qiita-%3d'
1: qiita-419
2: qiita-879
3: qiita-452
4: qiita-054
5: qiita-025
Au-dessus de l'échantillon 'qiita-%d%X%x%x%A%C%c%c%B%V%v%D%Q%q%Y%Z%z%W%L%l' Est abrégé au format '% {...}' 'qiita-%{dXxxACccBVvDQqYZzWLl}' Je peux le faire.
$  python ppwgen.py  -n 5 'qiita-%{dXxxACccBVvDQqYZzWLl}'
1: qiita-32b3eMjmeUolYkdFjsNj
2: qiita-3F84MNzfAOoLNt1Y8GSi
3: qiita-9A3dURxtAAovPg7V8p9b
4: qiita-4D47iTquuEiDKjsQ3bM4
5: qiita-87dcXGjkuIuCMk1H5u9x
Spécifiez le caractère à sélectionner avec '[...]' au lieu du spécificateur.
#Exemple de nombre binaire à 8 chiffres
$ python ppwgen.py  -n 5 '%8[01]'     
1: 01010110
2: 00100001
3: 10100111
4: 11011000
5: 00101110
Spécifiez le caractère à sélectionner avec '[' caractère de début '-' caractère de fin ']'.
#Choisissez parmi les lettres STUVWXYZ
$ python ppwgen.py -n 5 '%8[S-Z]'
1: XXTTZWTS
2: YUTTXUTV
3: UVUWXTXX
4: UTSZUWZS
5: UTWWYUVX
Le caractère qui suit immédiatement la barre oblique inverse \ n'a pas de signification particulière.
#Des lettres,-,Choisissez parmi 3 de Z
$ python ppwgen.py -n 5 '%8[S\-Z]'
1: -ZZ---S-
2: ZZZ--ZZZ
3: -ZZSS-SS
4: ZSS-SS-Z
5: Z----SZ-
Style de clé de licence
$ python ppwgen.py -n 10 'qiita%4{-c3d}'
 1: qiita-w119-i910-y458-q980
 2: qiita-j159-p127-u802-b125
 3: qiita-f923-o256-o568-h824
 4: qiita-k280-q899-a826-q831
 5: qiita-d264-a506-v904-q475
 6: qiita-u866-p655-n009-o483
 7: qiita-m101-a054-p896-x707
 8: qiita-o524-b339-j527-n802
 9: qiita-o030-k832-y107-s425
10: qiita-w842-a925-h295-p339
Répétez le numéro de la voyelle de la consonne.
$ python ppwgen.py -n 10 'qiita%4{-Qvqd}'
 1: qiita-Sap0-Woy0-Yeg6-Vig0
 2: qiita-Viq4-Giq7-Yoq0-Cam4
 3: qiita-Luz7-Woc8-Wek8-Xek0
 4: qiita-Saf8-Mac9-Kar4-Mif1
 5: qiita-Xen3-Kur3-Gix9-Mom4
 6: qiita-Xew6-Var0-Luf5-Guq9
 7: qiita-Gew8-Ded2-Jon0-Qac5
 8: qiita-Tiq2-Yef7-Reg3-Qiz9
 9: qiita-Paw8-Lap9-Jex7-Xuc2
10: qiita-Rud5-Yos6-Vam8-Pip8
Un motif complexe avec une structure imbriquée.
$ python ppwgen.py -n 10 'qiita%2{-C3{2c[13579]}}'
 1: qiita-Oqv5ct1eg9-Cfv3ha3yo1
 2: qiita-Vtw3yq5ka3-Nha9zh7vr1
 3: qiita-Ulk5yb3ne3-Dpz7wu5xu3
 4: qiita-Yqb1lg3uf5-Iqn5qy9xa1
 5: qiita-Qck5jr1ru1-Tgo9ab1rh3
 6: qiita-Vdc7tj3oj5-Iba3eu1yc3
 7: qiita-Pqn9wn1ws1-Ksb3ys5bt1
 8: qiita-Vpo7hq1wi7-Iyh3uc3lt1
 9: qiita-Fmq5mu3wh7-Tdd3gq7ea1
10: qiita-Sqb1iv1gb5-Boy9va7ve9