Générateur de mot de passe aléatoire

40

Le serveur de domaine requiert que tous les employés disposent d'un mot de passe fort et aléatoire, conforme aux règles suivantes:

  • Exactement 15 caractères.
  • Caractères saisis au clavier uniquement (comme indiqué dans le type de code ci-dessous). Apprendre aux vendeurs à utiliser les codes ALT + NUMPAD n'est pas autorisé.
  • Au moins 1 lettre minuscule: abcdefghijklmnopqrstuvwxyz
  • Au moins 1 lettre majuscule: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • Au moins 1 chiffre: 0123456789
  • Au moins 1 symbole: `~!@#$%^&*()_+-={}|[]\:";'<>?,./

À cette fin, le service informatique a commandé et distribuera un générateur de mot de passe aléatoire à tous les employés. Tous les employés devront utiliser le générateur de mot de passe aléatoire. En plus des restrictions de mot de passe ci-dessus, la configuration requise pour Random Password Generator est la suivante:

  • Il doit être capable de générer toutes les permutations de tous les caractères autorisés.
  • Il doit afficher le mot de passe généré à l'écran.
  • Le code doit être aussi petit que possible (en octets).

S'il vous plaît soumettre votre solution proposée dans la semaine prochaine.

Hand-E-Food
la source
10
Vous devez également exiger que tous les mots de passe autorisés apparaissent avec la même probabilité (sinon, je peux simplement faire une liste de 30 caractères avec des caractères autorisés, la mélanger et en donner les 15 premiers)
Martin Thoma Le
@ Moose, d'accord. J'ai ajouté une nouvelle règle.
Hand-E-Food
22
Les informaticiens devraient être licenciés, ou du moins mieux éduqués: si vous générez des mots de passe de manière aléatoire, limiter l'ensemble des mots de passe autorisés à ceux qui incluent au moins un caractère de chaque catégorie affaiblit les mots de passe car il réduit la taille des mots de passe. l'ensemble autorisé. Et nos programmes seraient d'autant plus faciles si nous n'avions pas à vérifier cela… D'accord, ne modifiez pas le concours après tant de soumissions arrivées; c'est bon comme défi.
MvG
10
@ MVG En effet:correcthorsebatterystaple
Jonathon Reinhart
1
Vous n'avez pas vraiment répondu à @ moose en exigeant que tous les mots de passe soient générables. Ils devraient apparaître avec une probabilité égale.
Ethan Bolker

Réponses:

29

Mathematica (18)

Laisse moi un peu tricher

= 15char ASCII pwd
&(^F7yP8k:*1P<t

PS pas de sécurité :)

Ybeltukov
la source
6
Où est le code?
DavidC
11
Est-ce que cela est garanti pour satisfaire au moins une exigence de chaque classe de caractères ?
Hand-E-Food
3
@ Hand-E-Food Oui, c'est bien ça! Si vous regardez l'interprétation, vous verrez: longueur du mot de passe 15, lettres minuscules requises, lettres majuscules requises, chiffres requis, caractères spéciaux requis.
ybeltukov
6
+1 intelligent, mais sournois.
DavidC
10
Je savais que Mathematica avait une fonction pour tout, mais ça ?
Konrad Borowski
13

Ruby, 74 69 octets

Juste un échantillon aléatoire de la gamme ascii 33 - 126 jusqu'à ce que toutes les classes de caractères soient présentes:

$_=[*?!..?~].sample(15)*''until~/\d/&&~/[a-z]/&&~/[A-Z]/&&~/\W|_/
p$_

Ruby, 39 octets

À l'aide de la découverte intelligente de l'orignal:

p"0123abcdABCD-+/<".chars.sample(15)*''

Modifier pour satisfaire la foule:

Notez que les règles ont changé après que j'ai posté ceci pour la première fois. Au moment où les deux entrées précédentes s'appliquaient aux règles. Je voudrais également souligner que les règles ne sont pas encore très bien définies:

(..) toutes les permutations de tous les caractères autorisés

"Permutations". Il n'y a pas de permutations des caractères autorisés qui soit conforme au reste des règles, car toute permutation de l'ensemble de caractères autorisés est aussi longue que l'ensemble de caractères autorisés lui-même (alors que le mot de passe est supposé comporter 15 caractères). Et il n'y a pas de répétition dans une permutation. Cependant, ma première entrée est encore plus "aléatoire" que la plupart des réponses bien plus votées ici.

Néanmoins, vous l'avez. Permet la répétition de caractères et de soulignement:

Ruby, 77 octets

$_=([*?!..?~]*15).sample(15)*''until~/\d/&&~/[a-z]/&&~/[A-Z]/&&~/\W|_/
puts$_

J'ai aussi utilisé à la putsplace de pcelui-ci carp imprime la chaîne entre guillemets et certains caractères échappés avec une barre oblique inverse.

Ruby, 70 octets

Comme Ventero le fait remarquer, ~peut être ignoré devant les expressions rationnelles et printpeut être remplacé puts$_. Mais avec la sortie laide que cela provoque, vous pouvez aussi bien imprimer tous les mots de passe rejetés, en les compressant dans un seul support:

puts$_=([*?!..?~]*15).sample(15)*''until/\d/&&/[a-z]/&&/[A-Z]/&&/\W|_/

Explication

Comme demandé. $_est une variable semi-magique qui contient la dernière ligne lue depuis l'entrée - vous n'avez donc pas toujours besoin de la stocker, comme ceci . Ici, cependant, nous l’utilisons à cause d’une autre propriété, à savoir que l’ ~opérateur lui applique directement une expression rationnelle, ce que j’ai appris en premier par chron . J'ai remplacé l'usage de all, mais il devrait être assez facile à comprendre si vous obtenez le reste ( voir la documentation ).

Daniero
la source
2
Pourriez-vous s'il vous plaît expliquer votre code un peu? Que fait .all?{|r|~r}-il? Que fait $_=-il?
Martin Thoma
3
La ligne d'échantillon est intelligente et tout, mais je pense qu'elle viole "Il doit être capable de générer toutes les permutations de tous les caractères autorisés." Nulle part il n'est dit que le mot de passe ne peut contenir qu'une annonce en ce qui concerne les lettres. Si z est un caractère autorisé, il devrait y avoir une chance> 0 que z soit dans le mot de passe.
nitro2k01
1
Est-ce que \WRuby inclut le trait de soulignement _? Dans la plupart des dialectes regex, je sais que ce n'est pas le cas. Et si votre code ne pouvait pas générer de mots de passe alors qu'un seul _était le seul symbole non alphanumérique, il contreviendrait à une exigence. La deuxième approche viole très évidemment cette exigence, mais j’imagine qu’elle n’était pas bien formulée à cette époque.
MvG
1
@ MVG: Vous avez raison. \Wne contient pas un trait de soulignement dans Perl RegEx compatible ( la source ).
Martin Thoma
1
De plus, votre solution est affectée par le même problème que @moose et moi avec Python: samplene répète pas les éléments, donc les mots de passe contenant des éléments répétés ne peuvent pas être générés par votre code. Pouvez-vous résoudre ces deux problèmes pour que votre réponse soit conforme à la question? Si votre solution est la meilleure, à l'exception de Wolfram Alpha, il serait bon de voir si vous pouvez vous conformer et conserver la tête. Je suppose que cela ne devrait pas être trop difficile.
MvG
12

Java 8 - 354 329 319 275 267 caractères

Juste pour vous amuser, utilisez lambdas avec Java 8 - chaque sortie possible a la même probabilité d’être trouvée.

Il utilise le fait que les caractères autorisés ont des codes ASCII consécutifs, allant de 33 à 126.

class A {
    //flags for, respectively, small caps, large caps, digits, punctuation
    static int a, A, d, p;

    public static void main(String[] x) {
        String s;
        do {
            //Using special String constructor that takes an int[]
            s = new String(new java.util.Random().ints(15, 33, 127)
                                .toArray(),
                           0, 15);
            a = A = d = p = 0;
            s.chars()
                .map(c ->
                      c > 96 & c < 123 ? a = 1
                    : c > 64 & c < 90  ? A = 1
                    : c > 47 & c < 58  ? d = 1
                    : (p = 1))
                .min();
        } while (a + A + d + p < 4);
        System.out.println(s);
    }
}

Exemple de sortie:

.*;Tm?svthiEK`3  
o.dzMgtW5|Q?ATo  
FUmVsu<4JF4eB]1

Programme compressé:

class A{static int a,A,d,p;public static void main(String[]x){String s;do{s=new String(new java.util.Random().ints(15,33,127).toArray(),0,15);a=A=d=p=0;s.chars().map(c->c>96&c<123?a=1:c>64&c<90?A=1:c>47&c<58?d=1:(p=1)).min();}while(a+A+d+p<4);System.out.println(s);}}

Assylias
la source
Que diriez-vous while(a+A+d+p<4)avec a|=1au lieu de a++? Ou encore, utilisez des masques de bits, c'est-à-dire des trucs comme à a|=1travers a|=8, avec a<15comme condition de boucle. Cela économise 13 caractères si je compte correctement.
MvG
@ MVG bon point - a fait quelque chose de similaire, sauvant quelques caractères supplémentaires, je crois.
Assylias
@ MVG Et l'utilisation new String(int[],int,int)enregistre une quarantaine de caractères!
Assylias
8

Python 2.X + 3.X (229 caractères): générer et remplacer

Idée

  1. D'abord faire une liste avec 15 symboles autorisés
  2. Remplacer une position aléatoire r par un chiffre aléatoire
  3. Remplacer une position aléatoire spars != r , par une lettre majuscule
  4. Même chose pour les lettres minuscules et les symboles que pour les symboles 2 et 3.

Code

from random import randint as r, shuffle as s
a=list(range(15))
p=a[:]
for i in range(15):
    a[i]=chr(r(32,126))
s(p)
a[p.pop()]=chr(r(48,57))
a[p.pop()]=chr(r(65,90))
a[p.pop()]=chr(r(97,122))
a[p.pop()]=chr(r(33,47))
print(a)

Python 2.X + 3.X (194 caractères): générer et vérifier

import random
from re import search as s
p=''
while not all([s("\d",p),s("[a-z]",p),s("[A-Z]",p),s("[\W_]",p)]):
 p=str(map(chr,[random.choice(list(range(33,127))) for i in range(15)]))
print(p)
  • Merci à MvG qui m’a dit cela \uet\l n’existe pas dans une regex Python.
  • Merci à grc qui m’a dit qu’il random.samplen’y avait pas de remplacement, soyez en mesure d’obtenir tous les mots de passe autorisés dont nous avons besoin.

Utilisation de la faille dans la description du problème

Actuellement, la description du problème n'exige pas que chaque symbole / chiffre apparaisse avec la même probabilité. Avec la solution suivante, vous ne pouvez faire aucune hypothèse sur un seul symbole et / ou une seule position. Mais vous pouvez le faire avec plusieurs.

Python 2.X + 3.X (62 caractères)

from random import sample
print(sample("0123abcdABCD-+/<",15))

Merci à daniero pour l'idée d'utiliser l'échantillon.

Martin Thoma
la source
Très facile à trouver la faille! J'ai branché celui-ci, mais des points bonus pour l'identifier. :-)
Hand-E-Food
Votre gen & check est similaire à mon approche. Par curiosité: où est-ce documenté \let ainsi de suite pour les regexes en python? Ne le voyez pas dans la référence . Mon Python 3.3.3 n'accepte même pas "\u". Le str(…)ne joint pas les lettres dans 3.3.3 ou 2.7.6. Une suggestion pour optmization: all(s("\\"+i,p)for i in "dluW").
MvG
random.samplechoisit des éléments sans les remplacer, de sorte que tous les mots de passe ne sont pas possibles.
grc
@ MVG: Merci. Je viens de voir cela \uet \lest vim-only.
Martin Thoma
7

Bash on * nix (109)

while ! grep -Pq [A-Z].*[a-z].*[0-9].*[\\W_]<<<$a$a$a$a
do a=`tr -dc !-~</dev/urandom|head -c15`
done
echo $a

Pour fonctionner correctement, vous $ane devez pas définir un mot de passe valide mais non aléatoire à l’avance. Si vous voulez inclure a=et séparer une ligne, cela fait trois caractères de plus, mais cela vous permet d’exécuter la chose à plusieurs reprises. Vous pouvez évidemment aussi remplacer toutes les nouvelles lignes par; afin que vous ayez une ligne que vous pouvez exécuter aussi souvent que vous le souhaitez.

De plus, vous devez avoir défini LC_ALL=Cou non des variables d’environnement spécifiques aux paramètres régionaux ( LANGetLC_CTYPE en particulier) , car les plages de caractères dépendent du fait que l’ordre de classement est égal à l’ordre ascii.

/dev/urandomest la source d'octets aléatoires. !-~est la plage de tous les caractères autorisés, comme spécifié dans la question. tr -dcsupprime tous les caractères non listés dans son argument suivant. headprend 15 des caractères restants. grepvérifie si chacun des types requis apparaît au moins une fois. Son entrée consiste en quatre copies du candidat. L'ordre des symboles n'a donc pas d'importance. Tous les mots de passe possibles ont donc une chance d'être sélectionnés. La -qgrep sortie de supprime.

Pour des raisons inconnues, /dev/randomau lieu de /dev/urandomprend des âges. Il semble que l'entropie se soit épuisée assez rapidement. Si vous cden /dev, vous pouvez éviter certains plus d' octets, mais qui se sent un peu comme la tricherie.

Python 2 (138)

import re,random
a=''
while not re.search('[A-Z].*[a-z].*[0-9].*[\W_]',a*4):
 a=''.join(random.sample(map(chr,range(33,127))*15,15))
print a

Pour rendre le code lisible, j'ai ajouté une nouvelle ligne et une indentation après la boucle, ce qui n'est pas nécessaire et que je n'ai pas compté.

C'est essentiellement la même idée que dans la version bash. La source aléatoire est ici random.sample, qui ne répétera pas les éléments. Pour contrer ce fait, nous utilisons 15 exemplaires de la liste des lettres autorisées. De cette façon, chaque combinaison peut encore se produire, bien que celles avec des lettres répétées se produisent moins souvent. Mais je décide de considérer cela comme une fonctionnalité et non comme un bug, car la question n'exigeait pas une probabilité égale pour toutes les permutations, mais seulement la possibilité.

Python 3 (145)

import re,random
a=''
while not re.search('[A-Z].*[a-z].*[0-9].*[\W_]',a*4):
 a=''.join(random.sample(list(map(chr,range(33,127)))*15,15))
print(a)

Une nouvelle ligne et un retrait à nouveau ne comptent pas. Hormis une surcharge de syntaxe spécifique à Python-3, il s'agit de la même solution que pour Python 2.

JavaScript (161)

a=[];for(i=33;i<127;)a.push(s=String.fromCharCode(i++));
while(!/[A-Z].*[a-z].*[0-9].*[\W_]/.test(s+s+s+s))
for(i=0,s="";i<15;++i)s+=a[Math.random()*94|0];alert(s)

J'ai ajouté les nouvelles lignes pour plus de lisibilité, mais je ne les ai pas comptées.

R (114)

s<-""
while(!grepl("[A-Z].*[a-z].*[0-9].*(\\W|_)",paste(rep(s,4),collapse="")))
 s<-intToUtf8(sample(33:126,15,T))
s

Le saut de ligne et l'indentation dans la boucle ont été ajoutés mais non comptés. Si vous en avez envie, vous pouvez à nouveau déplacer ceci sur une ;ligne à simple séparation.

MvG
la source
Ha! J'étais sur le point de préciser que vous auriez pu utiliser greplvotre code R. Si seulement j'avais pensé à répéter le mot de passe de test quatre fois pour pouvoir effectuer toutes les vérifications en même temps. Et vous savez, si seulement j'avais pensé à sampleet intToUtf8. Cependant, vous devez ajouter replace=TRUE(ou plus simplement, vous devez simplement ajouter ,T) à votre exemple de méthode pour vous assurer d'obtenir tous les mots de passe possibles.
AmeliaBR
@AmeliaBR: Vous avez raison, corrigé cette replace=Terreur, merci de l'avoir signalé. Trouver intToUtf8en devinant des noms probables en complétant l'onglet m'a pris un certain temps; Je savais qu'une telle fonction devait exister, mais les noms les plus communs tels que chret ainsi de suite n'étaient pas utilisés.
MvG
@ MVG: Je ne comprends pas pourquoi votre code Python se termine du tout. Pourquoi avez-vous besoin de ça *4? Je pensais que votre regex correspondrait à n'importe quelle chaîne, à cette annonce en premier une lettre majuscule, puis à n'importe quoi, puis à une lettre minuscule, à quoi que ce soit ... qu'est-ce que je me suis trompé?
Martin Thoma
@moose: Comme vous l'avez déjà remarqué, mon expression régulière vérifie les catégories requises dans un ordre spécifique. Mais en prenant la concaténation de quatre copies du candidat actuel, je peux m'assurer que l'ordre n'a plus d'importance: même si mon mot de passe est constitué de symboles suivis de chiffres suivis de minuscules suivis de majuscules, il y aurait toujours correspondance. Une correspondance ne peut échouer que si une catégorie manque complètement. Notez également que ce re.searchn'est pas le cas re.match, de sorte que l'expression régulière puisse correspondre n'importe où dans le mot de passe du candidat. Cela explique-t-il pourquoi il se terminera éventuellement?
MvG
Ah, je n'ai pas remarqué que vous utilisez re.searchau lieu de re.match. Ceci explique cela. Mais je pense toujours que tu n’as pas besoin de la *4. Merci pour l'explication (+1)
Martin Thoma
7

C # ( 123 - 139 103 - 127 caractères compactés):

Utiliser une méthode cadre parfaitement adéquate dans System.Web.dll:

class P
{
    static void Main()
    {
        Console.WriteLine(System.Web.Security.Membership.GeneratePassword(15, 1));
    }
}

Compacté:

class P{static void Main()
{Console.WriteLine(System.Web.Security.Membership.GeneratePassword(15,1));}}

Exemple:

b+m2ae0K:{dz7:A

Sinon, prenez la valeur du deuxième paramètre ( int numberOfNonAlphanumericCharacters) à partir de la ligne de commande:

class P
{
    static void Main(string[] a)
    {
        Console.WriteLine(System.Web.Security.Membership.GeneratePassword(15, int.Parse(a[0])));
    }
}
Rik
la source
3
GeneratePasswordne prend pas en charge l'ensemble des symboles spécifiés dans la question. Je n'ai pas non plus trouvé de garantie quant au nombre minimum d'occurrences de chaque catégorie de personnage.
MvG
2
Vous pouvez compacter davantage en utilisant class Pet string[] a.
d3dave
@ MVG, c'est intéressant. Il semble exclure tout symbole couramment utilisé pour écrire des caractères accentués dans des langues telles que le français. Probablement un geste intelligent. Changer la langue du clavier suffirait à donner votre mot de passe.
Aliments à la main
5

R (301 322 caractères)

La correction a oublié de vérifier les chiffres.

a='abcdefghijklmnopqrstuvwxyz';
f=as.factor(strsplit(paste(a,toupper(a),
    sep="0123456789`~!@#$%^&*()_+-={}|[]\\:\";'<>?,./"),"")[[1]]);
g=gsub("(.):","\\1",levels(q:q:q:q:q:q:q:q:q:q:q:q:q:q:q));
repeat{p=g[runif(1)*length(g)]; 
    if(grepl("[A-Z]",p)&&grepl("[a-z]",p)&&grepl("[0-9]",p)&&grepl("[^A-Za-z0-9]",p))break;};
print(p);

(espace ajouté pour plus de clarté).

Génère toutes les permutations possibles de 15 caractères des 94 caractères. Puis en sélectionne un au hasard jusqu'à ce qu'il corresponde aux critères.

La magie réside dans l' q:qopération, qui génère un nouveau type de données factoriel, à savoir l' interaction de tous les facteurs de la première qliste avec tous les facteurs de la seconde liste , toutes les combinaisons possibles de ces deux listes étant incluses dans la liste " niveaux "de ce facteur. Interagissez 15 copies de la liste des caractères autorisés et vous obtenez (94 ^ 15) niveaux possibles.

S'il vous plaît, n'essayez pas cela à la maison. Le code prend quelques secondes pour comprendre toutes les permutations à trois caractères. Je ne peux vraiment pas imaginer combien de temps il faudrait pour comprendre toutes les permutations à 15 caractères, si votre ordinateur ne manquait pas de mémoire en attendant. Lorsque j'ai exécuté le script terminé (mot de passe à trois caractères) pour le vérifier, le premier mot de passe qu'il a recruté était "oO =", ce qui, selon moi, résume la réaction que vous devriez avoir à l'égard de ce code.

AmeliaBR
la source
@MvG a un script R beaucoup plus pratique et beaucoup plus court, bien que beaucoup moins impressionnant: codegolf.stackexchange.com/a/17700/12413
AmeliaBR le
Néanmoins, j'aime votre idée. De nombreux extraits de code-golf que j'ai vus laissaient des caractéristiques spécifiques de la langue faire le travail difficile. Et votre code le fait certainement pour R, avec ces interactions.
MvG
4

Mathematica 170

r=RandomSample;f[i_]:=(FromCharacterCode/@Range@@i);
{t,A,a,n}=f/@{{33,126},{65,90},{97,122},{48,57}};
s=Complement[t,A,a,n];
""<>r[Join[RandomChoice/@{A,a,n,s},r[t,11]],15]

Exemples

"<]} Pg3 / e? 3 + Z ~ Oz"
"X / 8jWe @ f (_x5P: ="
"2wz2VQhtJC? * R7 ^"

DavidC
la source
4

Python 2.7 (182)

import random as r,string as s
z=r.sample
j=list(z(s.ascii_lowercase,12)+z(s.ascii_uppercase,1)+z(s.digits,1)+z('`~!@#$%^&*()_+-={}|[]\\:";\'<>?,./',1))
r.shuffle(j)
print ''.join(j)
Jonathon Reinhart
la source
Vous pouvez obtenir 9 chiffres de moins en supprimant la jointure car elle n'est pas requise par la description du problème. Encore 2 moins en supprimant les espaces.
Martin Thoma
@ moose j'ai retiré les espaces juste avant que vous ne commentiez :-) Je pense que le joingenre doit être là: les utilisateurs devraient-ils comprendre la syntaxe de la liste python à partir de la sortie ['q', 'u', ...]:?
Jonathon Reinhart
1
J'ai pensé à enlever les empreintes du tout. Lorsque la taille en octets est importante, ils peuvent vivre dans le temps de la carte perforée. De cette façon, ils pourraient peut-être lire la mémoire ... rien qu'en la regardant. Ou ce sont de "vrais programmeurs": xkcd.com/378
Martin Thoma
1
Si je lis correctement le code, cela ne remplira pas l'exigence de toutes les permutations , il aura toujours 12 caractères minuscules, ce qui rendra aA$bc1111111111impossible l' utilisation d'un mot de passe avec plusieurs des autres groupes (comme ).
IQAndreas
1
À la défense de Johnathon, je pense que la règle des permutations a été ajoutée 5 minutes après son poste.
Hand-E-Food
4

Golfscript (60)

Depuis l'obl. golfscript est manquant et en tant que noob j'ai besoin de la pratique quand même :)

[48 10{rand}:r~+65 26r+97 26r+33 15r+11,{;32 96r+}%~]{r}$''+

Il construit simplement un tableau avec les 4 caractères aléatoires requis + 11 et les trie dans un ordre aléatoire.

Joachim Isaksson
la source
+1 pour {r}$. C'est une façon assez sale de mélanger une liste - j'aime ça! ;-)
Ilmari Karonen
... Cependant, je ne pense pas que cela puisse jamais produire, par exemple 0Aa~~~~~~~~~~~~. :-(
Ilmari Karonen
3

JavaScript 258 240 233 225

R=Math.random;a=b=>b[b.length*R()|0];for(x=[a(l="abcdefghijklmnopqrstuvwxyz"),a(u=l.toUpperCase()),a(n="0123456789"),a(s="`~!@#$%^&*()_+-={}|[]\\:\";'<>?,./")];15>x.length;x.push(a(l+u+n+s)));alert(x.sort(y=>.5-R()).join(""))

En utilisant une règle où:

function(x){return x*x}peut être ré-écrit comme function(x)x*x. Ne semble fonctionner que pour les fonctions renvoyant une valeur.

Prochaine itération, réduite x.sort(function().5-R())àx.sort(y=>.5-R())

Prochaine itération, réduite davantage avec la notation de la flèche grasse, qui ne fonctionne malheureusement que pour Firefox 22 et les versions ultérieures.

WallyWest
la source
Beau compactage! : D
IQAndreas
2

JavaScript (269 caractères compactés)

Pour plus de clarté, voici le code avant de le compacter avec JS-Fiddle :

var lowerLetters = "abcdefghijklmnopqrstuvwxyz";
var upperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var numbers = "0123456789";
var symbols = "`~!@#$%^&*()_+-={}|[]\\:\";'<>?,./";
var allCharacters = lowerLetters + upperLetters + numbers + symbols;

String.prototype.randomChar = function() {
    return this[Math.floor(this.length * Math.random())];
}

var minLength = 15;
var result = [];

// Start off by picking one random character from each group
result.push(lowerLetters.randomChar());
result.push(upperLetters.randomChar());
result.push(numbers.randomChar());
result.push(symbols.randomChar());
// Next, pick a random character from all groups until the desired length is met
while(result.length < minLength) {
    result.push(allCharacters.randomChar());
}
result.shuffle(); // Finally, shuffle the items (custom function; doesn't actually exist in JavaScript, but is very easy to add) -> http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
result.join("");

Ici, il est réduit à 269 caractères (dont JS-Fiddle ):

l="abcdefghijklmnopqrstuvwxyz";
u=l.toUpperCase();
n="0123456789";
s="`~!@#$%^&*()_+-={}|[]\\:\";'<>?,./";
R=Math.random;

function r(t){
    return t[~~(t.length*R())]
}

for(x=[r(l),r(u),r(n),r(s)];x.length<15;x.push(r(l+u+n+s)));
x.sort(function(){return .5-R()});
alert(x.join(""));
IQAndreas
la source
Comme je termine les lignes par des points-virgules, tous les espaces amovibles ont été ignorés pour le comptage des caractères, mais laissés à l'intérieur pour des raisons de clarté.
IQAndreas
Qu'entendez-vous par shuffle()"fonction personnalisée"? Est-ce une partie de JavaScript ou du code que vous auriez à écrire vous-même?
Hand-E-Food
@ Hand-E-Food Je voulais dire que ce n'est pas intégré à JavaScript, et comme tous les développeurs ici doivent savoir comment mélanger un tableau, je me suis dit que l'inclusion de la fonction dans le code était inutile. Il est disponible dans le JS-Fiddle cependant (ligne 16).
IQAndreas
1
Mon point est, cela compte dans votre nombre d'octets. Mais je vois maintenant que vous l'avez implémenté dans la version compactée, alors ignorez-moi s'il vous plaît. :-)
Hand-E-Food le
2

Clojure (63):

(->> (map char (range 33 127)) (shuffle) (take 15) (apply str))

Mais il faut améliorer pour que celui-ci contienne au moins 1 caractère de chaque catégorie (Supérieur, Inférieur, Chiffre, Symbole).

ntalbs
la source
2

Dans sql-server

declare @a nvarchar(28)
set @a='abcdefghijklmnopqrstuvwxyz'
declare @b nvarchar(max)
set @b='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
declare @c nvarchar(max)
set @c='0123456789'
declare @d nvarchar(max)
set @d='~!@#$%^&*()_+-={}|[]\:";<>?,./'

select left(substring(@a,cast(rand()*10 as int),3)+substring(@b,cast(rand()*10 as int),6)+substring(@c,cast(rand()*10 as int),3)+substring(@d,cast(rand()*10 as int),5),15)

Voyez-le en action - 1

le voir en action - 2

Vhadalgi
la source
1
J'ai du mal à suivre la dernière ligne, mais le code ne semble pas satisfaire à l' exigence de toutes les permutations .
IQAndreas
Votre code ne générera jamais aucun mot de passe commençant par ~0Aa, ni aucun mot de passe bsuivi de a.
Heinzi
@Heinzi: oui, je suis d'accord avec toutes les permutations requises. R non pris en compte, il affiche simplement une longueur de 15. caractères choisis aléatoirement parmi a ... z, A..Z, 0..9,! ... + :(. ..
vhadalgi
2

SAS (191)

%macro c(p);compress(p,,"&p")ne''%mend;data x;length p$15;do x=1by 1;do t=1to 15;substr(p,t,1)=byte(ranuni(7)*94+33);end;if %c(kd)and %c(kl)and %c(ku)and %c(ad)then do;put p;stop;end;end;run;

*TQP,(f=h10*)S=

Commenté / en retrait:

%macro c(p); /*compress removes or keeps certain classes of characters*/
  compress(p,,"&p")ne''
%mend;
data x;
length p$15;
do x=1by 1;
    do t=1to 15;
        substr(p,t,1)=byte(ranuni(7)*94+33); /*give it a 33-126, byte discards the noninteger portion rounding down*/
    end;
    if %c(kd)and %c(kl)and %c(ku)and %c(ad)then do; /*k=keep d=digit l/u=lower/upper ad=remove digits and alphas*/
        put p;
        stop;  /*met our requirement, head home*/
    end;
end;
run;
Joe
la source
2

PowerShell: 119

Code Gofled

for(;!($x-cmatch'.*(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!-/:-@[-`{-~]).*')){$x='';1..15|%{$x+=[char](33..126|random)}}$x

Non-golfé et commenté

# Start for loop definition.
for(
    # Skip variable initialization, start definition of run condition.
    ;
    # Loop runs if $x does not meet complexity requirements.
    # Length requirement is not tested here because it is enforced by the generator later.
    # Much thanks to @VasiliSyrakis for the RegEx help.
    !($x-cmatch'.*(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!-/:-@[-`{-~]).*')
)
{
    # Reset $x in case the script block has already run.
    $x='';
    # Use ForEach-Object, via the % alias, to run a loop 15 times.
    1..15|%{
        # Append a random ASCII character from 33-126 to $x.
        # Note: Use get-random instead of random for faster performance.
        $x+=[char](33..126|random)
    }
}
# Display $x.
$x
# Variable cleanup - not included in golfed code.
rv x
Iszi
la source
Je pense que cette expression rationnelle peut le rendre un peu plus court: ^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$vous pouvez faire une correspondance avec celle-ci, ce qui ne se fera que s’il ya une seule majuscule, une minuscule, un chiffre et un symbole.
Vasili Syrakis
@VasiliSyrakis Ok, vous devrez peut-être me guider un peu. N'hésitez pas à démarrer une salle de discussion si vous pensez que cela prendra un certain temps. Quelques choses sur lesquelles je suis confus: 1.) Je vois le nombre 15 inclus. Est-ce que cela signifie que la chaîne contient exactement 15 caractères? Si tel est le cas, vous pouvez l'omettre, car le script ne génère naturellement que des chaînes de 15 caractères. 2.) Que voulez-vous dire "ne correspondra que s'il y a un symbole supérieur, inférieur, numérique, chiffre"? Cela signifie-t-il qu'il n'y aura de correspondance que s'il y en a exactement un ou au moins un? Le premier va casser des choses.
Iszi
De plus, votre RegEx ignore-t-il l'ordre des caractères? Par exemple, si l' écoute des chaînes vers le bas pour correspondre à 4 caractères, serait à la fois 1aZ%et (p3Rcorrespondre? J'ai eu du mal à trouver des moyens de le faire en ligne.
Iszi
Testé le nouveau RegEx par rapport à la sortie de mon script actuel. Cela ne semble pas assez fiable. Code: $x-cmatch'^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$'Bonnes correspondances: Correspondances manquées C>suD1?hTwbDx(z j%4O]HyeG|u[U$5 O/rGeD0$hJk=GO/: 3evthX3_X^nBrR` .nA ~ uYzrR4YV-r.`u-IjZE48ntQ;HxV
Iszi
Comment puis-je ouvrir une salle de discussion?
Vasili Syrakis
1

Python 2.7 (149)

from random import*
''.join(map(lambda x:chr(randint(*(x[1]or(32,126)))),sorted(map(None,sample(range(15),15),((48,57),(65,90),(97,122),(33,47))))))

Ecrit de manière plus lisible (et non exécutable);

from random import *
''.join(                                          # Concatenate characters to string
  map(                                            # Map all characters using below lambda
    lambda x:chr(randint(*(x[1] or (32, 126)))),  # Map a single range to a random character
                                                  # within a specific range if supplied,
                                                  # otherwise the default "all" range.
    sorted(                                       # After distributing ranges, sort
      map(None,                                   # zip_longest alternative, distributes the
                                                  # required ranges over 4 random positions
        sample(range(15), 15),                    # 0-14 in random order
        ((48, 57), (65, 90), (97, 122), (33, 47)) # The 4 required ranges
      )
    )
  )
)

Assez simple et étonnamment pas plus long qu'une version "générer, réessayer sur correspondance échec".

Joachim Isaksson
la source
Etes-vous sûr que cela peut vraiment générer tous les mots de passe éligibles, y compris par exemple 0Aa~~~~~~~~~~~~? (Notez que '~' == chr(126).)
Ilmari Karonen
1

PSQL (189)

On se sent comme PSQL est un peu prolixe ... :)

SELECT ARRAY_TO_STRING(ARRAY_AGG(CHR((TRUNC((b-a)*RANDOM()+a))::int)ORDER BY RANDOM()),'')FROM(SELECT 32 a,127 b FROM generate_series(1,11)UNION ALL VALUES(48,58),(65,91),(97,123),(33,48))a

Démo SQLfiddle .

Joachim Isaksson
la source
1

PHP, 235 225

Ce script mélange les caractères et est ensuite vérifié via RegEx pour s'assurer que le mot de passe est fort (ou qu'il est régénéré).

<?php
while(!preg_match('/^(?=.*[A-Z])(?=.*[^A-Za-z])(?=.*[0-9])(?=.*[a-z]).{15}$/',$p)){ $p = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()_+-={}|[]\:";\'<>?,./'),0,15); }
echo $p;
ub3rst4r
la source
1
Clever, mais n'autorise pas les doublons.
Hand-E-Food
1
Au lieu de while(true) ... if (condition) breakvous pouvez utiliserwhile (!condition)
Exussum
1

Javascript (209)

r=Math.random;function t(x,y){return String.fromCharCode(Math.floor(y*r()+x))};x=[t(33,14),t(48,10),t(65,26),t(97,26)];for(i=0;i<11;i++)x.push(t(32,95));console.log(x.sort(function(){return r()-0.5}).join(''))

Semi-ungolfé;

// Return a character in the range [x,x+y)
function t(x,y) { return String.fromCharCode(Math.floor(y*Math.random()+x)) }
// Prefill required ranges
x=[ t(33,14), t(48,10), t(65,26), t(97,26)]
// Push 11 totally random (valid) characters
for(i=0; i<11; i++)
  x.push(t(32,95))
// Shuffle and output as string
console.log(x.sort(function(){return Math.random()-0.5})
             .join(''))
Joachim Isaksson
la source
1

Perl, 92

Pas aussi concis que la réponse de Ruby, mais je suis sûr qu'un assistant de Perl pourrait rendre cela encore plus court ... Je ne suis pas trop content de tout ce qu'il y a m//à la fin, mais semble fonctionner et devrait satisfaire aux conditions pour éventuellement générer toutes les permutations.

do{$_=join"",map{(map{chr}33..127)[rand 94]}0..14}while!(/[A-Z]/&/[a-z]/&/\d/&/[\W_]/);print

Exemple d'utilisation:

perl -e 'do{$_=join"",map{(map{chr}33..127)[rand 94]}0..14}while!(/[A-Z]/&/[a-z]/&/\d/&/[\W_]/);print'

Modifié pour corriger la validation et passer [[:punct:]]à [\W_]après les commentaires MvG.

Dom Hastings
la source
1
Votre partie génération est agréable, mais votre critère de sélection dans la condition de boucle est tout à fait faux: par exemple, un mot de passe de aaaaaaaaaaaaaaprovoquerait la fin de la boucle. Vous devez tester les critères avec des mots de passe non aléatoires pour vous assurer qu'ils font ce que vous souhaitez.
MvG
En effet, vous avez raison, j'ai résolu ce problème et sauvegardé quelques octets! Merci!
Dom Hastings
1
Êtes-vous sûr de ça [[:punct:]]? Je suppose que je préférerais la , which is shorter and of which I'm even more sure that it is correct, at least combined with your gamme '[\ W_] 33..127`.
MvG
Un bon point, je pense que je craignais que \Wcela n'inclue pas _, cependant vous avez absolument raison, ce n'est pas nécessaire: gist.github.com/anonymous/8301237 . Merci!
Dom Hastings
1

Java 7 ( 270 234 caractères)

Le principe est le même que celui utilisé par @assylias avec java 8 (générer des mots de passe aléatoires jusqu’à obtention d’un mot de passe valide). Cependant, au lieu d'utiliser lambdas, le mot de passe est généré en itérant un tableau de caractères et validé en faisant correspondre une expression régulière.

class A {
  public static void main(String [] a) {
    byte[] b = new byte[15];
    String s;
    do {
      new java.util.Random().nextBytes(b);
      s = new String(b);
    } while(!s.matches("(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\\d)(?=.*?[!-/:-@\\[-`]).*"));
    System.out.println(s);
  }
}

Code minifié:

class A {public static void main(String[] a){byte[] b=new byte[15];String s;do{new java.util.Random().nextBytes(b);s=new String(b);}while(!s.matches("(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\\d)(?=.*?[!-/:-@\\[-`]).*"));System.out.println(s);}}
madoke
la source
1

Powershell


Version One Liner (143 octets)

sal g random;1..11|%{$P+=[char](33..126|g)};(65..90|g),(97..122|g),(48..57|g),(33..47+58..64+123..126|g)|%{$P=$P.insert((1..11|g),[char]$_)};$P

Version mini (146 octets)

sal g random
1..11|%{$P+=[char](33..126|g)}
(65..90|g),(97..122|g),(48..57|g),(33..47+58..64+123..126|g)|%{$P=$P.insert((1..11|g),[char]$_)}
$P

Version lisible (860 octets)

function pwgen {

    # Fulfill Upper,Lower,Digit,Symbol requirement by predefining ASCII ranges for each
    # These will be added into the string beginning at line 24

    [array[]]$symbolrange = (33..47),(58..64),(123..126)

    [char]$upper = (get-random (65..90))
    [char]$lower = (get-random (97..122))
    [char]$digit = (get-random (48..57))
    [char]$symbol = $symbolrange | get-random

    [char[]]$requirement = $upper + $lower + $digit + $symbol

    # Create the first 11 characters using any ASCII character between 32 - 126

    foreach ($number in (1..11)) {
        [string]$pass += [char](get-random (33..126))
    }

    # Insert each requirement character at a random position in the string

    foreach ($char in $requirement) {
        [string]$pass = $pass.insert((Get-Random (1..11)),$char)
    }

    return $pass
}

Nous remercions Iszi pour divers conseils pour raccourcir le code.

Vasili Syrakis
la source
1
Cela ne couvre pas toutes les permutations. Par exemple, abcd1234ABCD{|}~ne sera jamais évoqué car $symboloblige au moins l'un des symboles à se situer entre ASCII 33 et 47.
Hand-E-Food le
Dangit! Devez-vous signaler ma paresse!? Je plaisante ... je l'ai édité maintenant. J'ai également fait chaque caractère "exigence" aller à un index séparé dans la chaîne, au lieu d'agréger les quatre dans le même index. Maintenant, si seulement je pouvais abréger ça ...
Vasili Syrakis
Y a-t-il une raison pour laquelle vous ne pouvez pas raser quelques caractères de plus en raccourcissant $SRpeut $Q- être ?
Iszi
Vous devriez également être capable de couper des choses comme (g(65..90))les 65..90|g'. And change the instructions foreach` jusqu'à des foreach-objectboucles utilisant l' %alias. Exemple: foreach($N in (1..11)){... }devrait être faisable que 1..11|%{... }. Je suis presque sûr que d'autres optimisations sont possibles, mais j'ai en réalité une implémentation complètement différente que je prévois d'essayer plus tard.
Iszi
Astuces sympas :) Je l'ai raccourci à 213 octets si je retire les retours de chariot et les remplace par des points-virgules.
Vasili Syrakis
1

Facteur, 196 caractères

Même algorithme que MvG et Moose's. Ce n'est pas le plus court mais doit satisfaire à tous les critères (actuels) de la question:

USING: io kernel math pcre random sequences sequences.repeating ;
[ 15 94 random-integers [ 33 + ] "" map-as dup 60 cycle
"[A-Z].*[a-z].*[0-9].*[\\W_]" findall { } = not ] [ drop ] until print
Björn Lindqvist
la source
Je peux mal interpréter l'expression régulière, mais je pense que quelque chose comme ~{}|1234abcdABCDva échouer à l'expression régulière.
Hand-E-Food
1
Non cela fonctionnera:"~{}|1234abcdABCD" 60 cycle "[A-Z].*[a-z].*[0-9].*[\\W_]" findall empty? not => t
Björn Lindqvist le
Je te prendrai au mot. :-)
Hand-E-Food
1

C - 154 caractères

char p[16],c,f,w;main(){srand(time());while(f^15){c=p[15]=f=0;while(c^15){w=33+rand()%94;f|=w
>96&&w<123?1:w>47&&w<59?2:w>64&&w<91?4:8;p[c++]=w;}}puts(p);}

Comment je déteste srand()? Laisse-moi compter les chemins.

Oberon
la source
1

Haskell, 192

import System.Random
main=getStdGen>>= \g->(print.(take 15))$until((\x->all(any(`elem`x))[['a'..'z'],['A'..'Z'],['0'..'9'],['!'..'/']++":;<=>?@[\\]^_`{|}~"]).(take 15))tail$randomRs('"','~')g

La chaîne imprimée est entourée de guillemets et échappe aux barres obliques inverses et aux guillemets; si cela est inacceptable, printpeut être remplacé par putStrLn3 octets supplémentaires. Voici une version plus lisible:

import System.Random

main = do
    g <- getStdGen
    let chars = randomRs ('"', '~') g
    let password = take 15 $ until (hasChars.(take 15)) tail chars
    print password

hasChars :: String -> Bool
hasChars x = all (any (`elem` x)) $
    [ ['a'..'z']
    , ['A'..'Z']
    , ['0'..'9']
    , "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
    ]

C'est assez simple, il crée simplement une liste infinie / lazy de caractères ASCII aléatoires dans la plage '!'de '~', puis jette le premier élément jusqu'à ce que les 15 premiers caractères contiennent au moins un caractère de chaque chaîne de caractères requis.

utilisateur3175123
la source
1

Excel VBA, 209 octets

For i = 1 To 15
x = x + Chr(Int(90 * Rnd + 33))
Next
p = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$"
With New RegExp
.Pattern = p
Set m = .Execute(x)
If m.Count = 0 Then
MsgBox "redo"
Else
MsgBox x
End If
End With

Génère au hasard 15 caractères ASCII afin que toutes les combinaisons possibles soient possibles. Utilise ensuite un modèle d’expression régulière pour vérifier s’il contient au moins un de chaque critère.

Si c'est le cas, le mot de passe est affiché, sinon "redo" est affiché.

Nous remercions Bart Kiers pour le modèle d’expression régulière: https://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char- plus haut

Wightboy
la source
0

AutoHotkey 352

global o:={}
loop 4
o[c()]:=o(A_index-1)
loop 11
o[c()]:=o(m(r(),4))
loop 15
s.=o[A_index-1]
msgbox % s
r(){
Random,z
return z
}
m(z,r){
return mod(z,r)
}
c(){
while o[t:=m(r(),15)]!=""
j++
return t
}
o(f){
r0:=48,l0:=10,r1:=97,l1:=l2:=26,r2:=65
r := chr(r%f%+m(r(),l%f%))
if f=3
r:=Substr("``~!@#$%^&*()_+-={}|[]\:"";'<>?,./",m(r(),32)+1,1)
return r
}

Utiliser - Il suffit de lancer le script

Avi
la source
0

Python (121 caractères)

Utilise le fait que vous pouvez multiplier des listes en Python [1,2,3] * 2 donne [1,2,3,1,2,3]. Importations aléatoires. Les nombres dans une liste multipliés par trois sont des frontières entre les plages du tableau ascii pour les caractères nécessaires, par exemple [65, 90] mappent en lettres majuscules.

print "".join([random.choice([chr(i) for i in range(z[0],z[1])]) for z in [[33,48],[48,58],[58,65],[65,90],[90,123]]* 3])
Pawelmhm
la source
1
"Il doit être capable de générer toutes les permutations de tous les caractères autorisés.". Je ne pense pas que ce soit le cas, car les plages sont toujours appliquées dans le même ordre ...?
Joachim Isaksson
You are right, thank you. Indeed I didn't notice that ranges should be applied in random order, they should be shuffled, I'll edit that in a moment.
Pawelmhm
This needs to actually include import random in the code.
Mego
0

PHP 5.5 (230 bytes)

echo preg_replace_callback('/./', function ($a)
{
  return chr([rand(33, 126), rand(48, 57), rand(65, 90), rand(97, 122), ord(str_shuffle('`~!@#$%^&*()_+-={}|[]\:";\'<>?,./')[0])][$a[0]]);
}
, str_shuffle(str_pad('1234', 15, 0)));

Or on one line (211 bytes)

echo preg_replace_callback('/./',function($a){return chr([rand(33,126),rand(48,57),rand(65,90),rand(97,122),ord(str_shuffle('`~!@#$%^&*()_+-={}|[]\:";\'<>?,./')[0])][$a[0]]);},str_shuffle(str_pad('1234',15,0)));
MichaelRushton
la source