nur-sery/nur_src/passwd/AbstractGenerator.php

69 lines
2.1 KiB
PHP

<?php
namespace nur\passwd;
abstract class AbstractGenerator {
const NB_BLOCKS = 4;
const NB_PUNCTS = 2;
const CONSONNES = "bcdfghjklmnpqrstvwxz";
const VOYELLES = "aeiuoy";
const PUNCTS = "+-*/=!@?:#";
const MAPPINGS = [
# éviter certaines combinaisons potentiellement gênantes
"sexe" => "xese",
"sexy" => "xyse",
"suce" => "cesu",
"bite" => "tebi",
"cabo" => "boca",
"pipe" => "pepi",
"cocu" => "cuco",
"pute" => "tepu",
];
function __construct(?int $nbBlocks=null, ?int $nbPuncts=null) {
if ($nbBlocks === null) $nbBlocks = static::NB_BLOCKS;
if ($nbPuncts === null) $nbPuncts = static::NB_PUNCTS;
if ($nbBlocks < 1) $nbBlocks = 1;
if ($nbPuncts > $nbBlocks) $nbPuncts = $nbBlocks;
$this->nbBlocks = $nbBlocks;
$this->nbPuncts = $nbPuncts;
}
/** @var int */
protected $nbBlocks, $nbPuncts;
function generate(?int $nbBlocks=null, ?int $nbPuncts=null, ?int $seed=null): string {
if ($nbBlocks === null) $nbBlocks = $this->nbBlocks;
if ($nbPuncts === null) $nbPuncts = $this->nbPuncts;
if ($seed !== null) mt_srand($seed);
$maxc = strlen(self::CONSONNES) - 1;
$maxv = strlen(self::VOYELLES) - 1;
$maxp = strlen(self::PUNCTS) - 1;
$size = $nbBlocks * 2;
$sindex = 0;
$syllabes = [];
while ($sindex < $size) {
$lindex = count($syllabes) - 1;
do {
$consonne = self::CONSONNES[mt_rand(0, $maxc)];
$voyelle = self::VOYELLES[mt_rand(0, $maxv)];
$syllabe = $consonne.$voyelle;
# pas deux fois la même syllabe de suite
$repetition = ($lindex >= 0 && $syllabes[$lindex] == $syllabe)
|| ($lindex >= 1 && $syllabes[$lindex - 1] == $syllabe);
} while ($repetition);
$syllabes[] = $syllabe;
$sindex++;
if ($nbPuncts > 0 && $sindex % 2 == 0 && mt_rand() % 2 == 0) {
$syllabes[] = self::PUNCTS[mt_rand(0, $maxp)];
$nbPuncts--;
}
}
$password = implode("", $syllabes);
foreach (self::MAPPINGS as $from => $to) {
$password = str_replace($from, $to, $password);
}
return $password;
}
}