Notes › PC1
Voici plusieurs options, de la plus simple à la plus complète.
1. En une ligne (shell)
1
2
3
4
5
6
7
8
| # 24 caractères alphanumériques + symboles
tr -dc 'A-Za-z0-9!@#$%^&*()_+=-' < /dev/urandom | head -c 24; echo
# Avec openssl (base64, 24 caractères)
openssl rand -base64 18
# Avec pwgen (à installer : apt install pwgen / pacman -S pwgen)
pwgen -sy 24 5
|
2. Script shell
1
2
3
4
5
6
7
8
9
10
11
12
| #!/usr/bin/env bash
# genpass.sh : génère N mots de passe de longueur L
# Usage : ./genpass.sh [longueur] [nombre]
LEN="${1:-24}"
COUNT="${2:-1}"
CHARS='A-Za-z0-9!@#$%^&*()_+=,.?-'
for _ in $(seq "$COUNT"); do
LC_ALL=C tr -dc "$CHARS" < /dev/urandom | head -c "$LEN"
echo
done
|
1
2
| chmod +x genpass.sh
./genpass.sh 32 5
|
3. Script Python (recommandé)
Utilise le module secrets (cryptographiquement sûr, contrairement à random) et garantit au moins un caractère de chaque catégorie :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| #!/usr/bin/env python3
import argparse
import secrets
import string
def generate(length, symbols, no_ambiguous):
lower = string.ascii_lowercase
upper = string.ascii_uppercase
digits = string.digits
special = symbols
if no_ambiguous:
ambiguous = set("O0oIl1|`'\"")
lower, upper, digits, special = (
"".join(c for c in s if c not in ambiguous)
for s in (lower, upper, digits, special)
)
pools = [lower, upper, digits]
if special:
pools.append(special)
if length < len(pools):
raise SystemExit(f"Longueur minimale : {len(pools)}")
# Au moins un caractère de chaque catégorie
chars = [secrets.choice(p) for p in pools]
alphabet = "".join(pools)
chars += [secrets.choice(alphabet) for _ in range(length - len(chars))]
# Mélange sûr
secrets.SystemRandom().shuffle(chars)
return "".join(chars)
def main():
p = argparse.ArgumentParser(description="Générateur de mots de passe")
p.add_argument("-l", "--length", type=int, default=24)
p.add_argument("-n", "--count", type=int, default=1)
p.add_argument("-s", "--symbols", default="!@#$%^&*()-_=+[]{};:,.?",
help="symboles autorisés ('' pour aucun)")
p.add_argument("-a", "--no-ambiguous", action="store_true",
help="exclure les caractères ambigus (O/0, l/1/I...)")
args = p.parse_args()
for _ in range(args.count):
print(generate(args.length, args.symbols, args.no_ambiguous))
if __name__ == "__main__":
main()
|
Exemples :
1
2
3
4
| ./genpass.py # 1 mot de passe de 24 caractères
./genpass.py -l 32 -n 5 # 5 mots de passe de 32 caractères
./genpass.py -l 20 -a # sans caractères ambigus
./genpass.py -l 16 -s '' # alphanumérique uniquement (sites qui refusent les symboles)
|
4. Passphrase (mots aléatoires, plus facile à retenir)
1
2
3
4
5
6
7
| #!/usr/bin/env python3
import secrets
with open("/usr/share/dict/words") as f: # apt install wamerican
words = [w.strip() for w in f if w.strip().isalpha() and 4 <= len(w.strip()) <= 8]
print("-".join(secrets.choice(words) for _ in range(6)))
|
Conseils
- Évite
$RANDOM ou le module random de Python : non adaptés à la cryptographie.
- Certains sites refusent certains symboles : prévois l’option sans symboles (
-s '') en augmentant la longueur à 32 pour compenser.
- Si tu utilises KeePassXC, son générateur intégré (et
keepassxc-cli generate) fait aussi très bien le travail :
1
| keepassxc-cli generate -L 24 -l -u -n -s
|
Diceware
1. Outil tout fait
1
2
3
| pipx install diceware # ou : pip install --user diceware
diceware -n 6 -d - --no-caps # 6 mots séparés par des tirets
diceware --help # listes de mots disponibles (-w), dont d'autres langues selon la version
|
Alternative : xkcdpass (apt install xkcdpass).
2. Script Python avec la liste EFF
1
| curl -O https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| #!/usr/bin/env python3
import argparse
import secrets
def load(path):
# Format EFF : "11111<TAB>abacus"
with open(path, encoding="utf-8") as f:
return [line.split()[-1] for line in f if line.strip()]
def main():
p = argparse.ArgumentParser(description="Générateur diceware")
p.add_argument("-w", "--wordlist", default="eff_large_wordlist.txt")
p.add_argument("-n", "--words", type=int, default=6)
p.add_argument("-c", "--count", type=int, default=1)
p.add_argument("-d", "--sep", default="-")
p.add_argument("--digit", action="store_true",
help="ajoute un chiffre à la fin (sites qui l'exigent)")
args = p.parse_args()
words = load(args.wordlist)
for _ in range(args.count):
phrase = args.sep.join(secrets.choice(words) for _ in range(args.words))
if args.digit:
phrase += args.sep + str(secrets.randbelow(10))
print(phrase)
bits = args.words * len(words).bit_length()
print(f"# ~{args.words * __import__('math').log2(len(words)):.0f} bits d'entropie",
file=__import__('sys').stderr)
if __name__ == "__main__":
main()
|
1
| ./diceware.py -n 7 -c 3
|
3. Shell pur (sans Python)
1
| shuf --random-source=/dev/urandom -n 6 eff_large_wordlist.txt | cut -f2 | paste -sd'-'
|
4. Vrais dés
Lance 5 dés par mot, cherche le nombre obtenu (ex. 43125) dans la liste :
1
| grep -P '^43125\t' eff_large_wordlist.txt
|
Entropie
La liste EFF large contient 7776 mots (6⁵), soit environ 12,9 bits par mot :
| Mots |
Entropie |
| 5 |
~65 bits (minimum pour un usage courant) |
| 6 |
~77 bits (bon compromis) |
| 7 |
~90 bits (mot de passe maître, chiffrement de disque) |
L’entropie vient du tirage aléatoire, pas des mots eux-mêmes. Ne choisis jamais les mots toi-même et ne relance pas jusqu’à obtenir une phrase qui te plaît. Pour un mot de passe maître KeePassXC ou une passphrase LUKS, 7 mots est un bon choix.