Generatore di password casuali


40

Il server di dominio richiede che tutti i dipendenti dispongano di una password sicura e casuale conforme alle seguenti regole:

  • Esattamente 15 caratteri.
  • Solo caratteri tipizzabili da tastiera (come mostrato di seguito nel tipo di codice). Non è consentito insegnare alle vendite a utilizzare i codici ALT + NUMPAD.
  • Almeno 1 lettera minuscola: abcdefghijklmnopqrstuvwxyz
  • Almeno 1 lettera maiuscola: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • Almeno 1 cifra numerica: 0123456789
  • Almeno 1 simbolo: `~!@#$%^&*()_+-={}|[]\:";'<>?,./

A tale scopo l'IT ha commissionato e distribuirà un generatore di password casuali a tutti i dipendenti. Tutti i dipendenti dovranno utilizzare il generatore di password casuali. I requisiti per il generatore di password casuali sono, oltre alle restrizioni sulla password di cui sopra:

  • Deve essere in grado di generare tutte le permutazioni di tutti i caratteri consentiti.
  • Deve visualizzare la password generata sullo schermo.
  • Il codice deve essere il più piccolo possibile (in byte).

Invia la soluzione proposta entro la prossima settimana.


10
Dovresti anche richiedere che tutte le password consentite appaiano con la stessa probabilità (altrimenti posso semplicemente fare un elenco di 30 caratteri con caratteri consentiti, rimescolarlo e fornire i primi 15)
Martin Thoma

@moose, d'accordo. Ho aggiunto una nuova regola.
Hand-E-Food

22
I ragazzi IT dovrebbero essere licenziati, o almeno meglio istruiti: se si generano password in modo casuale, quindi limitare l'insieme delle password consentite a quelle che includono almeno un carattere di ogni categoria indebolisce le password, poiché riduce le dimensioni di il set consentito. E i nostri programmi sarebbero molto più facili se non dovessimo verificarlo ... OK, non modificare il concorso dopo che sono arrivati ​​così tanti invii; va bene come una sfida.
MvG


1
Non hai davvero risposto a @moose richiedendo che tutte le password siano generabili. Dovrebbero apparire con uguale probabilità.
Ethan Bolker,

Risposte:


29

Mathematica (18)

Mi permetta di imbrogliare

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

PS non di sicurezza :)


6
Dov'è il codice?
DavidC,

11
È garantito che soddisfi almeno uno dei requisiti di ciascuna classe di caratteri ?
Hand-E-Food

3
@ Hand-E-Food Sì, lo è! Se guardi l'interpretazione, vedrai: lunghezza della password 15, lettere minuscole richieste, lettere maiuscole richieste, numeri richiesti, caratteri speciali richiesti.
ybeltukov,

6
+1 intelligente, ma subdolo.
DavidC,

10
Sapevo che Mathematica ha una funzione per tutto, ma questo ?
Konrad Borowski il

13

Rubino, 74 69 byte

Basta campionare casualmente dall'intervallo ascii 33 - 126 fino a quando tutte le classi di caratteri sono presenti:

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

Rubino, 39 byte

Usando la scoperta intelligente di alci:

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

Modifica per soddisfare il mob:

Nota che le regole sono cambiate dopo che l' ho pubblicato per la prima volta. Al momento entrambe le voci precedenti si applicavano alle regole. Vorrei anche sottolineare che le regole non sono ancora ben definite:

(..) tutte le permutazioni di tutti i caratteri consentiti

"Permutazioni". Non ci sono nessun permutazioni dei caratteri consentiti che è conforme con il resto delle regole, perché ogni permutazione del set di caratteri consentiti è lungo come l'insieme di caratteri consentiti stesso (mentre la password dovrebbe essere di 15 caratteri). E non ci sono ripetizioni in una permutazione. Comunque la mia prima voce è ancora più "casuale" di molte altre risposte ben votate qui.

Tuttavia, qui ce l'hai. Consente ripetizioni di caratteri e trattini bassi:

Rubino, 77 byte

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

Ho usato anche putsinvece di pquesto perché pstampa la stringa racchiusa tra "virgolette" e alcuni caratteri sono sfuggiti a una barra rovesciata.

Rubino, 70 byte

Come sottolinea Ventero, ~può essere saltato davanti alle regex e printpuò essere sostituito puts$_. Ma con l'output brutto questo può causare anche la stampa di tutte le password rifiutate, stringendole in una riga:

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

Spiegazione

Come richiesto. $_è una variabile semi-magica che contiene l'ultima riga letta dall'input, quindi non è sempre necessario memorizzarla, in questo modo . Qui tuttavia lo usiamo a causa di un'altra proprietà, vale a dire che l' ~operatore applica una regex direttamente ad esso, un trucco che ho appreso per la prima volta da chron . Ho sostituito l'uso di all, ma dovrebbe essere abbastanza facile capire se ottieni il resto ( vedi i documenti ).


2
Potresti spiegare un po 'il tuo codice? Cosa fa .all?{|r|~r}? Cosa fa $_=?
Martin Thoma,

3
La linea di esempio è intelligente e tutto, ma penso che violi "Deve essere in grado di generare tutte le permutazioni di tutti i caratteri consentiti". Da nessuna parte si dice che la password può contenere annunci solo per quanto riguarda le lettere. Se z è un carattere consentito, dovrebbe esserci una possibilità> 0 che z sia nella password.
nitro2k01,

1
Fa \Win Ruby includono la sottolineatura _? Nella maggior parte dei dialetti regex so che non lo è. E se il tuo codice non fosse in grado di generare password in cui una singola _era l'unico simbolo non alfanumerico, violerebbe un requisito. Il secondo approccio viola ovviamente tale requisito, ma immagino che non sia stato formulato correttamente in quel momento.
MvG

1
@MvG: hai ragione. \Wnon contiene un carattere di sottolineatura in RegEx ( sorgente ) compatibile con Perl .
Martin Thoma,

1
Inoltre, la tua soluzione è influenzata dallo stesso problema che ho riscontrato con @moose con Python: samplenon ripete gli elementi, quindi le password con elementi ripetuti non possono essere generate dal tuo codice. Puoi risolvere questi due problemi per rendere la tua risposta conforme alla domanda? Vedendo come la tua è la soluzione principale, ad eccezione di Wolfram Alpha, sarebbe bello vedere se puoi conformarti e mantenere comunque la guida. Immagino che non dovrebbe essere troppo difficile.
MvG

12

Java 8 - 354 329 319 275 267 caratteri

Solo per divertimento, usando lambdas con Java 8 - ogni possibile output ha la stessa probabilità di essere trovato.

Utilizza il fatto che i caratteri consentiti hanno codici ASCII consecutivi, da 33 a 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);
    }
}

Uscita campione:

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

Programma compresso:

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);}}


Che ne dici di while(a+A+d+p<4)insieme a|=1invece di a++? Oppure usa maschere di bit, cioè cose come a|=1through a|=8, con a<15come condizione di loop. Ciò consente di risparmiare altri 13 caratteri se ho contato correttamente.
MvG

@MvG buon punto - ho fatto qualcosa di simile, salvando un paio di caratteri extra credo.
Assylias,

@MvG E l'utilizzo new String(int[],int,int)salva altri 40 caratteri dispari!
Assylias,

8

Python 2.X + 3.X (229 caratteri): genera e sostituisce

Idea

  1. Prima fai un elenco con 15 simboli consentiti
  2. Sostituisci una posizione casuale rcon una cifra casuale
  3. Sostituisci una posizione casuale s, con s != r, con una lettera maiuscola
  4. Lo stesso per lettere minuscole e simboli come in 2 e 3.

Codice

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 caratteri): Genera e controlla

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)
  • Grazie a MvG che me lo ha detto \ue \lnon esiste nel regex di Python.
  • Grazie a grc che mi ha detto che random.sampleè senza sostituzione, sia per ottenere tutte le possibili password consentite che abbiamo bisogno di campionare con la sostituzione.

Utilizzo del difetto nella descrizione del problema

Attualmente, la descrizione del problema non richiede che ogni simbolo / cifra appaia con la stessa probabilità. Con la seguente soluzione, non è possibile formulare ipotesi su un singolo simbolo e / o posizione. Ma puoi farlo con più di uno.

Python 2.X + 3.X (62 caratteri)

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

Grazie a daniero per l'idea di usare il campione.


Molto facile trovare il difetto! L'ho collegato, ma punti bonus per identificarlo. :-)
Hand-E-Food

Il tuo gen & check è simile al mio approccio. Per curiosità: dove sono documentati questo \le così via per le regex di Python? Non vederlo nel riferimento . My Python 3.3.3 non accetta nemmeno "\u". Il str(…)non unisce le lettere in 3.3.3 o 2.7.6. Un suggerimento per ottimizzazioni: all(s("\\"+i,p)for i in "dluW").
MvG

random.samplesceglie elementi senza sostituzione, quindi non tutte le password sono possibili.
GRC

@MvG: grazie. L'ho appena visto \ued \lè solo vim.
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

Per funzionare correttamente, $anon deve essere impostato su una password valida ma non casuale in anticipo. Se vuoi includere a=e una linea spezzata in avanti, ci sono altri tre personaggi ma ti consente di eseguire ripetutamente la cosa. Ovviamente puoi anche sostituire tutte le nuove linee in ;modo da avere un solo liner che puoi eseguire tutte le volte che desideri.

Inoltre, è necessario impostare LC_ALL=Co meno le variabili di ambiente specifiche della locale ( LANGe LC_CTYPEin particolare), poiché gli intervalli di caratteri dipendono dall'ordine di confronto che è uguale all'ordine ascii.

/dev/urandomè la fonte di byte casuali. !-~è l'intervallo di tutti i caratteri consentiti, come specificato nella domanda. tr -dcrimuove tutti i caratteri non elencati nel prossimo argomento. headprende 15 dei personaggi rimanenti. grepcontrolla se ciascuno dei tipi richiesti si verifica almeno una volta. Il suo input consiste in quattro copie del candidato, quindi l'ordine dei simboli non ha importanza, quindi tutte le possibili password hanno la possibilità di essere selezionate. Il -qgrep sopprime l'output.

Per ragioni sconosciute, /dev/randominvece di /dev/urandomrichiedere secoli. Sembra che l'entropia si sia esaurita abbastanza rapidamente. Se cdin /dev, è possibile evitare alcuni più byte, ma che si sente un po 'come barare.

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

Per rendere leggibile il codice ho aggiunto una nuova riga e un rientro dopo il ciclo che non sono necessari e che non ho contato.

Questa è essenzialmente la stessa idea della versione bash. La fonte casuale qui è random.sample, che non ripeterà gli elementi. Per contrastare questo fatto, utilizziamo 15 copie dell'elenco delle lettere consentite. In questo modo, ogni combinazione può ancora verificarsi, anche se quelli con lettere ripetute si verificano meno spesso. Ma decido di considerare questa una caratteristica, non un bug, poiché la domanda non ha richiesto la stessa probabilità per tutte le permutazioni, solo 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)

Una nuova riga e un rientro non vengono conteggiati. A parte alcuni overhead di sintassi specifici di Python-3, questa è la stessa soluzione di 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)

Ho aggiunto le nuove righe per la leggibilità, ma non le ho contate.

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

Interruzione di riga e rientro all'interno del loop aggiunti ma non conteggiati. Se ne hai voglia, puoi di nuovo spostarlo su una ;riga separata.


Ha! Stavo per sottolineare che avresti potuto usare il grepltuo codice R. Se solo avessi pensato di ripetere la password di prova quattro volte in modo da poter fare tutti i controlli in uno. E sai, se solo ci avessi pensato samplee intToUtf8. Tuttavia, devi aggiungere replace=TRUE(o più concisamente, devi solo aggiungere ,T) al tuo metodo di esempio per assicurarti di ottenere tutte le password possibili.
AmeliaBR,

@AmeliaBR: hai ragione, risolto replace=Tquell'errore, grazie per averlo segnalato. Trovare intToUtf8indovinando i nomi probabili con il completamento della scheda mi ha richiesto un po 'di tempo; Sapevo che una tale funzione doveva esistere, ma i nomi più comuni come chre così via non venivano usati.
MvG

@MvG: non capisco perché il tuo codice Python si interrompa affatto. Perché ne hai bisogno *4? Pensavo che il tuo regex corrispondesse a qualsiasi stringa, quell'annuncio prima una lettera maiuscola, poi qualsiasi cosa, poi una lettera minuscola, che altro ... cosa ho sbagliato?
Martin Thoma,

@moose: Come hai già notato, il mio regex controlla le categorie richieste in un ordine specifico. Ma prendendo la concatenazione di quattro copie dell'attuale candidato, posso garantire che l'ordine non conta più: anche se la mia password è rappresentata da simboli seguiti da cifre seguite da lettere minuscole seguite da lettere maiuscole, allora ci sarebbe ancora una corrispondenza. L'unico modo in cui una partita può fallire è se una categoria manca del tutto. Si noti inoltre che faccio re.search, non re.match, quindi la regex potrebbe corrispondere in qualsiasi parte della password candidato. Questo spiega perché alla fine terminerà?
MvG

Ah, non ho notato che usi re.searchinvece di re.match. Questo lo spiega. Ma penso ancora che non ti serva *4. Grazie per la spiegazione (+1)
Martin Thoma,

7

C # ( 123 - 139 103 - 127 caratteri compattati):

Utilizzando un metodo quadro perfettamente adeguato in System.Web.dll:

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

Compatto:

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

Esempio:

b+m2ae0K:{dz7:A

In alternativa, prendi il valore del secondo parametro ( int numberOfNonAlphanumericCharacters) dalla riga di comando:

class P
{
    static void Main(string[] a)
    {
        Console.WriteLine(System.Web.Security.Membership.GeneratePassword(15, int.Parse(a[0])));
    }
}

3
GeneratePasswordnon supporta il set completo di simboli specificato nella domanda. Né ho trovato alcuna garanzia sul numero minimo di occorrenze di ciascuna categoria di personaggi.
MvG

2
È possibile compattare ulteriormente utilizzando class Pe string[] a.
d3dave,

@MvG, è interessante. Sembra che escluda qualsiasi simbolo comunemente usato per scrivere caratteri accentati in lingue come il francese. Probabilmente una mossa intelligente. Cambiare la lingua della tastiera sarebbe sufficiente per riempire la tua password.
Hand-E-Food,

5

R (301 322 caratteri)

Correzione dimenticata di verificare la presenza di cifre.

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);

(spazi bianchi aggiunti solo per chiarezza).

Genera tutte le possibili permutazioni di 15 caratteri dei 94 caratteri. Quindi ne seleziona uno a caso fino a quando non corrisponde ai criteri.

La magia sta q:qnell'operazione, che genera un nuovo tipo di dati fattore che è l' interazione di tutti i fattori nel primo qelenco con tutti i fattori nel secondo elenco , con ogni possibile combinazione di quei due elenchi inclusa nell'elenco di " livelli "di quel fattore. Interagisci 15 copie dell'elenco dei personaggi consentiti e ottieni (94 ^ 15) livelli possibili.

Per favore, non provarlo a casa. Il codice impiega un paio di secondi per capire tutte le permutazioni di tre caratteri, non riesco davvero a immaginare quanto tempo ci vorrebbe per capire tutte le permutazioni di 15 caratteri, se il tuo computer non si esaurisse nella memoria frattempo. Quando ho eseguito lo script finito (password di tre caratteri) per controllarlo, la prima password che ha emesso è stata "oO =", che penso riassuma la reazione che dovresti avere a questo codice.


@MvG ha uno script R che è allo stesso tempo molto più pratico e molto più breve, anche se molto meno eccezionale: codegolf.stackexchange.com/a/17700/12413
AmeliaBR

Tuttavia, mi piace la tua idea. Molti frammenti di code-golf che ho visto lasciano che funzioni specifiche della lingua facciano il duro lavoro. E il tuo codice lo fa certamente per R, con quelle interazioni.
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]

Esempi

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


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)

È possibile ottenere 9 cifre in meno rimuovendo il join in quanto non è richiesto dalla descrizione del problema. Altri 2 in meno rimuovendo gli spazi.
Martin Thoma,

@moose ho tirato fuori gli spazi a destra prima commentato :-) Mi sento come il joingenere di deve essere lì: gli utenti ci si aspetterebbe da capire lista python sintassi dal: ['q', 'u', ...]?
Jonathon Reinhart,

1
Ho pensato di rimuovere la stampa. Quando la dimensione in byte è importante, potrebbero vivere nel tempo della scheda perforata. In questo modo, potrebbero essere in grado di leggere la memoria ... semplicemente guardandola. Oppure sono "veri programmatori": xkcd.com/378
Martin Thoma,

1
Se sto leggendo correttamente il codice, questo non soddisfa i requisiti di tutte le permutazioni , avrà sempre 12 caratteri minuscoli, rendendo impossibili le password con più di uno degli altri gruppi (come aA$bc1111111111).
IQAndreas

1
In difesa di Johnathon, penso che la regola delle permutazioni sia stata aggiunta 5 minuti dopo il suo posto.
Hand-E-Food

4

Golfscript (60)

Dal momento che l'obl. manca golfscript e comunque come un noob ho bisogno della pratica :)

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

Costruisce solo un array con i 4 caratteri + 11 casuali richiesti e in ordine casuale.


+1 per {r}$. È un modo piuttosto sporco di mescolare un elenco: mi piace! ;-)
Ilmari Karonen il

... tuttavia, non credo che questo possa mai produrre ad es 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(""))

Utilizzando una regola in cui:

function(x){return x*x}può essere riscritto come function(x)x*x. Sembra funzionare solo per le funzioni che restituiscono un valore.

Prossima iterazione, ridotta x.sort(function().5-R())ax.sort(y=>.5-R())

Prossima iterazione, ulteriormente ridotta con la notazione a freccia grossa, che purtroppo funziona solo per Firefox 22 e versioni successive.


Bella compattazione! : D
IQAndreas

2

JavaScript (269 caratteri compattati)

Per chiarezza, questo è il codice prima di compattarlo su 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("");

Qui è ridotto a 269 caratteri ( JS-Fiddle di esso ):

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(""));

Dal momento che sto terminando le linee con punti e virgola, tutti gli spazi bianchi rimovibili sono stati ignorati per il conteggio dei personaggi, ma sono stati lasciati per chiarezza.
IQAndreas

Che cosa intendi per shuffle()essere una "funzione personalizzata". Fa parte di JavaScript o codice che dovresti scriverlo tu stesso?
Hand-E-Food

@ Hand-E-Food. Volevo dire che non è incorporato in JavaScript e, dal momento che tutti gli sviluppatori qui dovrebbero sapere come mescolare un array, ho ritenuto che la funzione nel codice non fosse necessaria. È disponibile nel JS-Fiddle (linea 16).
IQAndreas

1
Il punto è che conta per il conteggio dei byte. Ma ora vedo che l'hai implementato nella versione compatta, quindi per favore ignorami. :-)
Hand-E-Food

2

Clojure (63):

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

Ma deve essere migliorato per garantire che contenga almeno 1 carattere di ogni categoria (Superiore, Inferiore, Cifra, Simbolo).


2

In 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)

Guardalo in azione - 1

vederlo in Azione - 2


1
Ho problemi a seguire l'ultima riga, ma il codice non sembra soddisfare tutti i requisiti di permutazioni .
IQAndreas

Il tuo codice non genererà mai alcuna password a partire da ~0Aa, né alcuna password dove bè seguito da a.
Heinzi,

@Heinzi: sì, sono d'accordo che tutte le permutazioni richieste non sono state prese in considerazione, mostra solo una lunghezza di 15 caratteri .. scelti casualmente da una ... 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=

Commentate / rientrato:

%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;

2

PowerShell: 119

Codice Gofled

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

Non golfato e commentato

# 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

Penso che questo regex possa renderlo leggermente più breve: ^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$puoi fare una partita con questa, che corrisponderà solo quando c'è un simbolo Superiore, Inferiore, Cifra, Simbolo.
Vasili Syrakis,

@VasiliSyrakis Ok, potresti dovermi guidare un po '. Sentiti libero di avviare una chat room se pensi che ci vorrà del tempo. Un paio di cose su cui sono confuso: 1.) Vedo il numero 15 incluso lì. È per assicurarsi che la stringa abbia esattamente 15 caratteri? In tal caso, questo può essere omesso, poiché lo script genera naturalmente solo stringhe di 15 caratteri. 2.) Cosa intendi per "corrisponderà solo quando c'è un simbolo superiore, inferiore, cifra,"? Ciò significa che corrisponderà solo quando ce n'è esattamente uno di ciascuno o almeno uno di ciascuno? Il primo romperà le cose.
Iszi,

Inoltre, RegEx ignora l'ordinamento dei personaggi? Ad esempio, se regolato verso il basso per abbinare stringhe di 4 caratteri, entrambi 1aZ%e (p3Rcorrisponderebbero? Ho avuto qualche difficoltà a trovare modi per farlo online.
Iszi,

Testato il nuovo RegEx sull'output del mio script corrente. Non sembra abbastanza affidabile. Codice: $x-cmatch'^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$'Buone partite: Partite C>suD1?hTwbDx(z j%4O]HyeG|u[U$5 O/rGeD0$hJk=GO/non 3evthX3_X^nBrR` riuscite : .nA ~ uYzrR4YV-r.`u-IjZE48ntQ;HxV
Iszi

Come faccio ad aprire una chat room?
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))))))

Scritto in un modo più leggibile (e non eseguibile);

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
      )
    )
  )
)

Abbastanza semplice e sorprendentemente non molto più lungo di una versione "genera, riprova a una partita fallita".


Sei sicuro che questo possa davvero generare tutte le password idonee, incluso ad esempio 0Aa~~~~~~~~~~~~? (Nota '~' == chr(126).)
Ilmari Karonen,

1

PSQL (189)

Sembra che PSQL sia un po 'prolisso ... :)

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

Demo di SQLfiddle .


1

PHP, 235 225

Questo script mescola i caratteri e quindi viene controllato tramite RegEx per assicurarsi che la password sia sicura (o rigenerata).

<?php
while(!preg_match('/^(?=.*[A-Z])(?=.*[^A-Za-z])(?=.*[0-9])(?=.*[a-z]).{15}$/',$p)){ $p = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()_+-={}|[]\:";\'<>?,./'),0,15); }
echo $p;

1
Intelligente, ma non consente caratteri duplicati.
Hand-E-Food

1
Invece di while(true) ... if (condition) breakte puoi usarewhile (!condition)
exussum il

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-ungolfed;

// 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(''))

1

Perl, 92

Non così conciso come la risposta di Ruby, ma sono sicuro che un mago Perl potrebbe renderlo ancora più breve ... Non sono troppo contento di tutte le m//s alla fine, ma sembra funzionare e dovrebbe soddisfare le condizioni per generare alla fine tutte le permutazioni.

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

Esempio di utilizzo:

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

Modificato per correggere la convalida e passare [[:punct:]]a [\W_]dopo i commenti MvGs.


1
La tua parte di generazione è buona, ma il tuo criterio di selezione nella condizione del loop è chiaramente sbagliato: ad es. Una password di aaaaaaaaaaaaaafarebbe terminare il loop. È necessario testare i criteri con password non casuali per assicurarsi che facciano ciò che si desidera.
MvG

Anzi, hai ragione, ho risolto questo problema e salvato alcuni byte! Grazie!
Dom Hastings,

1
Ne sei sicuro [[:punct:]]? Immagino che preferirei l'intervallo '[\ W_] , which is shorter and of which I'm even more sure that it is correct, at least combined with your 33..127`.
MvG

Un buon punto, penso di essere preoccupato che \Wnon includesse _, tuttavia hai assolutamente ragione, non è necessario: gist.github.com/anonymous/8301237 . Grazie!
Dom Hastings,

1

Java 7 ( 270 234 caratteri)

La premessa è la stessa usata da @assylias con java 8 (genera password casuali fino a password valida). Tuttavia, invece di utilizzare lambdas, la password viene generata ripetendo un array di caratteri e convalidata abbinando un regex.

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);
  }
}

Codice minimizzato:

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);}}

1

PowerShell


Versione One Liner (143 byte)

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

Versione mini (146 byte)

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

Versione leggibile (860 byte)

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
}

Ringraziamo Iszi per vari suggerimenti per abbreviare il codice.


1
Questo non copre tutte le permutazioni. Ad esempio, abcd1234ABCD{|}~non verrà mai fuori perché $symbolforza almeno uno dei simboli tra ASCII 33 e 47.
Hand-E-Food

Dangit! Devi sottolineare la mia pigrizia !? Sto scherzando ... L'ho modificato ora. Ho anche fatto in modo che ogni carattere "requisito" passasse a un indice separato all'interno della stringa, anziché raggruppare i quattro insieme nello stesso indice. Ora, se solo potessi accorciare questo ...
Vasili Syrakis il

C'è qualche motivo per cui non puoi radere un altro paio di personaggi accorciando $SR, forse $Q?
Iszi,

Si dovrebbe anche essere in grado di roba tagliata come (g(65..90))verso il basso per 65..90|g'. And change the le dichiarazioni foreach` al foreach-objectloop utilizzando l' %alias. Esempio: foreach($N in (1..11)){... }dovrebbe essere fattibile come 1..11|%{... }. Sono abbastanza sicuro che ci siano altre ottimizzazioni possibili, ma in realtà ho in mente un'implementazione completamente diversa che sto pensando di provare in seguito.
Iszi,

Bei consigli :) L'ho ridotto a 213 byte se estraggo i ritorni a capo e lo sostituisco con punti e virgola.
Vasili Syrakis,

1

Fattore, 196 caratteri

Stesso algoritmo di MvG e di alci. Non è il più breve ma dovrebbe soddisfare tutti i criteri (attuali) nella domanda:

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

Potrei interpretare male la regex, ma penso che qualcosa del genere ~{}|1234abcdABCDfallirà la regex.
Hand-E-Food

1
No, funzionerà:"~{}|1234abcdABCD" 60 cycle "[A-Z].*[a-z].*[0-9].*[\\W_]" findall empty? not => t
Björn Lindqvist,

Prenderò la tua parola per questo. :-)
Hand-E-Food

1

C - 154 caratteri

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);}

Come odio srand()? Lasciatemi contare i modi.


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 stringa stampata ha delle virgolette attorno e sfugge alla barra rovesciata e ai caratteri di virgoletta; se ciò è inaccettabile, printpuò essere sostituito con putStrLnaltri 3 byte. Ecco una versione più leggibile:

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']
    , "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
    ]

E 'molto semplice, si crea solo un infinito / lista pigro di caratteri ASCII casuali nella gamma '!'a '~', poi getta fuori il primo elemento fino a quando i primi 15 personaggi hanno almeno un personaggio di ciascuna stringa di caratteri richiesti.


1

Excel VBA, 209 byte

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

Genera casualmente 15 caratteri ASCII in modo che siano possibili tutte le combinazioni possibili. Quindi utilizza un modello di espressione regolare per verificare se contiene almeno uno di ciascun criterio.

In tal caso viene visualizzata la password, in caso contrario viene visualizzato "Ripeti".

Ringraziamo Bart Kiers per il modello di espressione regolare: https://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char- superiore


0

Tasto di scelta automatica 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
}

Utilizzo : basta eseguire lo script


0

Python (121 caratteri)

Si avvale del fatto che è possibile moltiplicare le liste in Python [1,2,3] * 2 da [1,2,3,1,2,3]. Importazioni casuali. I numeri in un elenco moltiplicati per tre sono bordi tra gli intervalli nella tabella ASCII per i caratteri necessari, ad esempio [65, 90] viene mappato a lettere maiuscole.

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])

1
"Deve essere in grado di generare tutte le permutazioni di tutti i caratteri consentiti.". Non credo che lo faccia dal momento che gli intervalli sono sempre applicati nello stesso ordine ...?
Joachim Isaksson,

Hai ragione, grazie. In effetti non ho notato che gli intervalli dovrebbero essere applicati in ordine casuale, dovrebbero essere mescolati, lo modificherò tra un momento.
Pawelmhm,

Questo deve effettivamente includere import randomnel codice.
Mego

0

PHP 5.5 (230 byte)

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)));

O su una riga (211 byte)

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)));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.