Random Password Generator

40

O servidor de domínio exige que todos os funcionários tenham uma senha forte e aleatória, em conformidade com as seguintes regras:

  • Exatamente 15 caracteres.
  • Apenas caracteres digitáveis ​​pelo teclado (conforme mostrado no tipo de código abaixo). Ensinar as vendas a usar os códigos ALT + NUMPAD não é permitido.
  • Pelo menos 1 letra minúscula: abcdefghijklmnopqrstuvwxyz
  • Pelo menos 1 letra maiúscula: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • Pelo menos 1 dígito numérico: 0123456789
  • Pelo menos 1 símbolo: `~!@#$%^&*()_+-={}|[]\:";'<>?,./

Para esse fim, a TI encomendou e distribuirá um Gerador de senha aleatória a todos os funcionários. Todos os funcionários deverão usar o Gerador de senha aleatória. Os requisitos para o Gerador de senha aleatória são, além das restrições de senha acima:

  • Ele deve ser capaz de gerar todas as permutações de todos os caracteres permitidos.
  • Ele deve exibir a senha gerada na tela.
  • É necessário que o código seja o menor possível (em bytes).

Envie sua solução proposta dentro da próxima semana.

Mão-E-Comida
fonte
10
Você também deve exigir que todas as senhas permitidas apareçam com a mesma probabilidade (caso contrário, posso simplesmente fazer uma lista de 30 caracteres com caracteres permitidos, embaralhá-la e fornecer as 15 primeiras)
Martin Thoma
@ moose, concordou. Eu adicionei uma nova regra.
Hand-E-Food
22
Os profissionais de TI devem ser demitidos ou, pelo menos, com melhor educação: se você gerar senhas aleatoriamente, restringir o conjunto de senhas permitidas àquelas que incluem pelo menos um caractere de cada categoria enfraquece as senhas, pois reduz o tamanho de senhas. o conjunto permitido. E nossos programas seriam muito mais fáceis se não tivéssemos que verificar isso ... OK, não modifique o concurso depois que tantas inscrições chegarem; está bem como um desafio.
MvG
10
@MvG Indeed:correcthorsebatterystaple
Jonathon Reinhart
11
Você realmente não respondeu à @moose exigindo que todas as senhas sejam geráveis. Eles devem aparecer com igual probabilidade.
precisa saber é o seguinte

Respostas:

29

Mathematica (18)

Deixe-me um pouco de trapaça

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

PS não segurança :)

ybeltukov
fonte
6
Cadê o código?
DavidC
11
Isso é garantido para atender a pelo menos um de cada requisito de classe de personagem ?
Hand-E-Food
3
@ Mão-E-Comida Sim, é! Se você observar a interpretação, verá: comprimento da senha 15, letras minúsculas necessárias, letras maiúsculas necessárias, números necessários, caracteres especiais necessários.
precisa saber é o seguinte
6
+1 Inteligente, mas sorrateiro.
DavidC
10
Eu sabia que o Mathematica tem uma função para tudo, mas isso ?
21978 Konrad Borowski
13

Ruby, 74 69 bytes

Faça uma amostra aleatória do intervalo de ascii 33 - 126 até que todas as classes de caracteres estejam presentes:

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

Ruby, 39 bytes

Usando a descoberta inteligente de alce:

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

Edite para satisfazer a multidão:

Observe que as regras foram alteradas depois que eu publiquei isso pela primeira vez. No momento, as duas entradas anteriores se aplicavam às regras. Gostaria também de salientar que as regras ainda não estão muito bem definidas:

(..) todas as permutações de todos os caracteres permitidos

"Permutações". Não permutações dos caracteres permitidos que estejam em conformidade com o restante das regras, porque qualquer permutação do conjunto de caracteres permitidos é tão longa quanto o próprio conjunto de caracteres permitidos (enquanto a senha deve ter 15 caracteres). E não há repetições em uma permutação. No entanto, minha primeira entrada é ainda mais "aleatória" do que muitas das outras respostas bem votadas aqui.

No entanto, aqui está. Permite repetições de caracteres e sublinhado:

Ruby, 77 bytes

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

Eu também usei no putslugar pdeste porque pimprime a cadeia de caracteres entre "aspas" e alguns caracteres escapam com uma barra invertida.

Ruby, 70 bytes

Como Ventero aponta, ~pode ser pulado na frente dos regexes e printpode ser substituído puts$_. Mas com a saída feia, isso faz com que você também possa imprimir todas as senhas rejeitadas, comprimindo-as em uma única linha:

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

Explicação

Como pedido. $_é uma variável semi-mágico que contém a última linha ler da entrada - para que você não precisa sempre de armazená-lo, como este . Aqui, porém, a usamos por causa de outra propriedade, a saber, que o ~operador aplica uma regex diretamente a ela, um truque que aprendi pela primeira vez por chron . Substituí o uso de all, mas deve ser bem fácil entender se você tem o restante ( consulte os documentos ).

daniero
fonte
2
Você poderia explicar um pouco o seu código? O que .all?{|r|~r}faz? O que $_=faz?
Martin Thoma
3
A linha de amostra é inteligente e tudo, mas acho que viola "Ele deve ser capaz de gerar todas as permutações de todos os caracteres permitidos". Em nenhum lugar diz que a senha pode conter apenas anúncios no que diz respeito às letras. Se z for um caractere permitido, deve haver uma chance> 0 de que z esteja na senha.
Nitro2k01
11
Será que \Wem Ruby incluem o sublinhado _? Na maioria dos dialetos regex eu sei que não. E se o seu código não pudesse gerar senhas em que um _fosse o único símbolo não alfanumérico, isso violaria um requisito. A segunda abordagem viola muito obviamente esse requisito, mas acho que não foi redigido corretamente naquele momento.
MvG
11
@MvG: Você está correto. \Wnão contém um sublinhado no RegEx compatível com Perl ( origem ).
Martin Thoma
11
Além disso, sua solução é afetada pelo mesmo problema que @moose e eu tive com o Python: samplenão repete elementos; portanto, senhas com elementos repetidos não podem ser geradas pelo seu código. Você pode corrigir esses dois problemas para tornar sua resposta conforme a pergunta? Vendo como a sua é a solução líder, exceto o Wolfram Alpha, seria bom verificar se você pode se conformar e ainda manter a liderança. Eu acho que não deve ser muito difícil.
MvG
12

Java 8 - 354 329 319 275 267 caracteres

Apenas por diversão, usando lambdas com Java 8 - cada saída possível tem a mesma probabilidade de ser encontrada.

Ele usa o fato de que os caracteres permitidos têm códigos ASCII consecutivos, de 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);
    }
}

Saída de amostra:

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

Programa compactado:

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
fonte
Que tal while(a+A+d+p<4)junto com em a|=1vez de a++? Ou use máscaras de bits, ou seja, coisas como a|=1through a|=8, com a<15a condição loop. Isso economiza outros 13 caracteres se eu contei corretamente.
MvG
@MvG good point - fez algo parecido, economizando alguns caracteres extras, acredito.
assylias
@MvG E usar new String(int[],int,int)salva outros 40 caracteres ímpares!
Assilias
8

Python 2.X + 3.X (229 caracteres): gere e substitua

Idéia

  1. Primeiro faça uma lista com 15 símbolos permitidos
  2. Substitua uma posição aleatória rpor um dígito aleatório
  3. Substituir uma posição aleatória s, com s != r, por uma letra maiúscula
  4. O mesmo para letra minúscula e símbolo como em 2 e 3.

Código

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 caracteres): Gere e verifique

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)
  • Obrigado ao MvG, que me disse isso \ue \lnão existe no regex do Python.
  • Graças ao grc, que me disse que random.sampleé sem substituição, seja para obter todas as senhas permitidas possíveis, precisamos de amostragem com substituição.

Usando falha na descrição do problema

Atualmente, a descrição do problema não exige que todos os símbolos / dígitos apareçam com a mesma probabilidade. Com a solução a seguir, você não pode fazer nenhuma suposição sobre um único símbolo e / ou posição. Mas você pode fazer isso com vários.

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

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

Agradeço a daniero pela ideia de usar a amostra.

Martin Thoma
fonte
Muito bom encontrar a falha! Liguei esse, mas pontos de bônus para identificá-lo. :-)
Hand-E-Food
Sua geração e seleção são semelhantes à minha abordagem. Por curiosidade: onde está isso \le assim por diante para os regexes python documentados? Não o veja na referência . Meu Python 3.3.3 nem aceita "\u". O str(…)não une as letras em 3.3.3 ou 2.7.6. Uma sugestão para Otimização: all(s("\\"+i,p)for i in "dluW").
MvG
random.sampleescolhe elementos sem substituição, para que nem todas as senhas sejam possíveis.
grc
@MvG: Obrigado. Acabei de ver isso \ue \lé apenas para vim.
Martin Thoma
7

Bash em * 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

Para funcionar corretamente, $anão deve ser definido com uma senha válida, mas não aleatória, com antecedência. Se você deseja incluir a=e uma quebra de linha na frente, são mais três caracteres, mas permite executar a coisa repetidamente. Obviamente, você também pode substituir todas as novas linhas ;por uma única linha que possa ser executada quantas vezes desejar.

Além disso, você deve definir LC_ALL=Cou não variáveis ​​de ambiente específicas do código do idioma ( LANGe LC_CTYPEem particular), pois os intervalos de caracteres dependem da ordem de intercalação igual à ordem ascii.

/dev/urandomé a fonte de bytes aleatórios. !-~é o intervalo de todos os caracteres permitidos, conforme especificado na pergunta. tr -dcremove todos os caracteres não listados em seu próximo argumento. headleva 15 dos caracteres restantes. grepverifica se cada um dos tipos necessários ocorre pelo menos uma vez. Sua entrada consiste em quatro cópias do candidato; portanto, a ordem dos símbolos não importa; portanto, todas as senhas possíveis têm chance de serem selecionadas. O -qto grep suprime a saída.

Por razões desconhecidas, em /dev/randomvez de /dev/urandomlevar idades. Parece que a entropia se esgotou muito rapidamente. Se você cdpara /dev, você pode evitar mais alguns bytes, mas que se sente um pouco como fazer batota.

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

Para tornar o código legível, adicionei uma nova linha e recuo após o loop, que não é necessário e que não contei.

Esta é essencialmente a mesma ideia que na versão bash. A fonte aleatória aqui é random.sample, que não repetirá elementos. Para combater esse fato, usamos 15 cópias da lista de cartas permitidas. Dessa forma, todas as combinações ainda podem ocorrer, embora aquelas com letras repetidas ocorram com menos frequência. Mas decido considerar isso um recurso, não um bug, já que a pergunta não exigia igual probabilidade para todas as permutações, apenas a possibilidade.

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)

Uma nova linha e um recuo novamente não são contados. Além de algumas sobrecargas de sintaxe específicas do Python-3, esta é a mesma solução do 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)

Eu adicionei as novas linhas para facilitar a leitura, mas não as contei.

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

Quebra de linha e recuo dentro do loop foram adicionados, mas não contados. Se quiser, você pode movê-lo novamente para uma ;linha separada.

MvG
fonte
Ha! Eu estava prestes a salientar que você poderia ter usado greplno seu código R. Se ao menos eu tivesse pensado em repetir a senha do teste quatro vezes para que você pudesse fazer todas as verificações em uma. E você sabe, se eu tivesse pensado sobre samplee intToUtf8. No entanto, você precisa adicionar replace=TRUE(ou mais concisamente, apenas adicionar ,T) ao seu método de amostra para garantir que você esteja obtendo todas as senhas possíveis.
AmeliaBR
@AmeliaBR: Você está certo, corrigiu esse replace=Terro, obrigado por apontar isso. Encontrar intToUtf8adivinhando nomes prováveis ​​com a conclusão da guia me levou um bom tempo; Eu sabia que essa função deveria existir, mas os nomes mais comuns como chre assim por diante não foram usados.
MvG
@MvG: Eu não entendo por que o seu código Python termina. Por que você precisa disso *4? Eu pensei que seu regex corresponderia a qualquer sequência, esse anúncio primeiro uma letra maiúscula, depois qualquer coisa, depois uma letra minúscula do que qualquer coisa ... o que eu entendi errado?
Martin Thoma
@ moose: Como você já percebeu, minha regex verifica as categorias necessárias em uma ordem específica. Mas, tomando a concatenação de quatro cópias do candidato atual, posso garantir que a ordem não importa mais: mesmo que minha senha seja símbolos seguidos por dígitos seguidos por dígitos seguidos por letras minúsculas e maiúsculas, ainda haverá uma correspondência. A única maneira de uma correspondência falhar é se uma categoria estiver totalmente ausente. Observe também que re.searchnão re.match, portanto, o regex pode corresponder a qualquer lugar da senha do candidato. Isso explica por que terminará eventualmente?
MvG
Ah, eu não percebi que você usa em re.searchvez de re.match. Isso explica tudo. Mas ainda acho que você não precisa do *4. Obrigado pela explicação (+1)
Martin Thoma
7

C # ( 123 - 139 103 - 127 caracteres compactados):

Usando um método de estrutura perfeitamente adequado em System.Web.dll:

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

Compactado:

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

Exemplo:

b+m2ae0K:{dz7:A

Como alternativa, pegue o valor do segundo parâmetro ( int numberOfNonAlphanumericCharacters) na linha de comando:

class P
{
    static void Main(string[] a)
    {
        Console.WriteLine(System.Web.Security.Membership.GeneratePassword(15, int.Parse(a[0])));
    }
}
Rik
fonte
3
GeneratePasswordnão suporta o conjunto completo de símbolos especificado na pergunta. Também não encontrei garantias sobre o número mínimo de ocorrências de cada categoria de personagem.
MvG
2
Você pode compactar ainda mais usando class Pe string[] a.
D3dave
@MvG, isso é interessante. Parece que exclui qualquer símbolo comumente usado para escrever caracteres acentuados em idiomas como o francês. Provavelmente uma jogada inteligente. Alterar o idioma do teclado seria suficiente para encher sua senha.
Mão-E-Comida
5

R (301 322 caracteres)

A correção esqueceu de verificar os dígitos.

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

(espaço em branco adicionado apenas para maior clareza).

Gera todas as permutações possíveis de 15 caracteres dos 94 caracteres. Em seguida, seleciona aleatoriamente um até que corresponda aos critérios.

A mágica está na q:qoperação, que gera um novo tipo de dado de fator que é a interação de todos os fatores da primeira qlista com todos os fatores da segunda lista , com todas as combinações possíveis dessas duas listas incluídas na lista de " níveis "desse fator. Interaja 15 cópias da lista de caracteres permitidos e você obtém (94 ^ 15) níveis possíveis.

Por favor não tente isto em casa. O código leva alguns segundos para descobrir todas as permutações de três caracteres. Realmente não consigo imaginar quanto tempo levaria para descobrir todas as permutações de 15 caracteres, se o computador não tivesse apenas memória insuficiente no enquanto isso. Quando executei o script finalizado (senha de três caracteres) para verificá-lo, a primeira senha que ele cuspiu foi "oO =", que eu penso resume a reação que você deve ter com esse código.

AmeliaBR
fonte
@MvG tem um script de R que é muito mais prático e muito mais curto, se muito menos impressionantes: codegolf.stackexchange.com/a/17700/12413
AmeliaBR
No entanto, eu gosto da sua ideia. Muitos trechos de código-golfe que vi permitiram que recursos específicos da linguagem fizessem o trabalho duro. E seu código certamente faz isso para R, com essas interações.
MvG 07/01
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]

Exemplos

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

DavidC
fonte
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
fonte
Você pode obter 9 dígitos a menos removendo a junção, pois não é exigida pela descrição do problema. Outros 2 a menos removendo espaços.
Martin Thoma
@ moose Tirei os espaços logo antes de você comentar :-) Eu sinto que o jointipo de coisa deve estar lá: seria esperado que os usuários entendessem a sintaxe da lista python a partir da saída ['q', 'u', ...]:?
Jonathon Reinhart
11
Pensei em remover a impressão. Quando o tamanho em bytes é importante, eles podem viver no tempo do cartão perfurado. Dessa forma, eles podem ler a memória ... apenas olhando para ela. Ou eles são "os programadores reais": xkcd.com/378
Martin Thoma
11
Se estou lendo o código corretamente, isso não atende a todos os requisitos de permutações , sempre terá 12 caracteres em minúsculas, impossibilitando senhas com mais de um dos outros grupos (como aA$bc1111111111).
precisa saber é o seguinte
11
Em defesa de Johnathon, acho que a regra de permutações foi adicionada 5 minutos depois de seu cargo.
Mão-E-Comida
4

Golfe (60)

Desde o obl. golfscript está faltando e como um noob eu preciso da prática de qualquer maneira :)

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

Ele apenas cria uma matriz com os 4 caracteres aleatórios necessários + 11 e ordena em ordem aleatória.

Joachim Isaksson
fonte
+1 para {r}$. Essa é uma maneira bastante suja de embaralhar uma lista - eu gosto! ;-)
Ilmari Karonen
... no entanto, não acho que isso possa gerar, por exemplo 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(""))

Usando uma regra em que:

function(x){return x*x}pode ser reescrito como function(x)x*x. Apenas parece funcionar para funções que retornam um valor.

Próxima iteração, reduzida x.sort(function().5-R())parax.sort(y=>.5-R())

Próxima iteração, reduzida ainda mais com a notação de seta gorda, que infelizmente só funciona para o Firefox 22 e superior.

WallyWest
fonte
Boa compactação! : D
IQAndreas
2

JavaScript (269 caracteres compactados)

Para maior clareza, este é o código antes de compactá-lo no 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("");

Aqui, ele é compactado em 269 caracteres ( 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
fonte
Como estou terminando linhas com ponto-e-vírgula, todo o espaço em branco removível foi ignorado para a contagem de caracteres, mas deixado para maior clareza.
precisa saber é o seguinte
O que você quer dizer com shuffle()"função personalizada". É parte do JavaScript ou código que você teria que escrever por conta própria?
Mão-E-Comida
@ Hand-E-Food, quis dizer que não está embutido no JavaScript e, como qualquer desenvolvedor aqui deve saber como embaralhar uma matriz, senti que incluir a função no código era desnecessário. Está disponível no JS-Fiddle (linha 16).
IQAndreas
11
O que quero dizer é que conta para a sua contagem de bytes. Mas agora vejo que você o implementou na versão compactada, então, por favor, me ignore. :-)
Mão-E-Comida
2

Clojure (63):

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

Mas precisa ser aprimorado para garantir que contenha pelo menos 1 caractere de cada categoria (Superior, Inferior, Dígito, Símbolo).

ntalbs
fonte
2

No servidor sql

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)

Veja em ação - 1

veja em Ação - 2

vhadalgi
fonte
11
Estou tendo problemas para seguir a última linha, mas o código não parece atender a todos os requisitos de permutações .
IQAndreas
Seu código nunca gerará nenhuma senha iniciada com ~0Aa, nem qualquer senha bseguida por a.
Heinzi
@ Heinzi: sim, eu concordo que todas as permutações necessárias não sejam levadas em consideração, apenas exibem 15 caracteres de comprimento ... escolhidos aleatoriamente a partir de ... 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=

Comentado / recuado:

%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
fonte
2

PowerShell: 119

Código Gofled

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

Sem golfe e comentado

# 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
fonte
Eu acho que esse regex pode torná-lo um pouco mais curto: ^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$você pode fazer uma correspondência com isso, que só corresponderá quando houver um símbolo superior, inferior, dígito e dígito.
Vasili Syrakis
@VasiliSyrakis Ok, talvez você precise me explicar um pouco. Sinta-se à vontade para iniciar uma sala de bate-papo, se achar que isso levará algum tempo. Estou confuso em algumas coisas: 1.) Vejo o número 15 incluído lá. Isso é para garantir que a string tenha exatamente 15 caracteres? Nesse caso, isso pode ser omitido, pois o script naturalmente gera apenas seqüências de 15 caracteres. 2.) O que você quer dizer com "corresponderá somente quando houver um símbolo Superior, Inferior, Dígito,"? Isso significa que só corresponderá quando houver exatamente um de cada, ou pelo menos um de cada? O primeiro vai quebrar as coisas.
Iszi
Além disso, seu RegEx ignora a ordem dos caracteres? Por exemplo, se ajustado para corresponder a seqüências de quatro caracteres, ambos 1aZ%e (p3Rcorresponderiam? Tive alguma dificuldade em encontrar maneiras de fazer isso online.
Iszi
Testei o novo RegEx em relação à saída do meu script atual. Não parece muito confiável. Código: $x-cmatch'^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$'Boas correspondências: Correspondências com C>suD1?hTwbDx(z j%4O]HyeG|u[U$5 O/rGeD0$hJk=GO/falha: 3evthX3_X^nBrR` .nA ~ uYzrR4YV-r.u-IjZE48ntQ;HxV
Iszi
Como abro uma sala de chat?
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))))))

Escrito de maneira mais legível (e não executável);

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

Bastante direto e surpreendentemente não muito mais do que uma versão "gerar, tentar novamente ao falhar na correspondência".

Joachim Isaksson
fonte
Tem certeza de que isso realmente pode gerar todas as senhas elegíveis, incluindo, por exemplo 0Aa~~~~~~~~~~~~? (Note-se que '~' == chr(126).)
Ilmari Karonen
1

PSQL (189)

Parece que o PSQL é um pouco detalhado ... :)

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

Demonstração do SQLfiddle .

Joachim Isaksson
fonte
1

PHP, 235 225

Esse script embaralha os caracteres e é verificado via RegEx para garantir que a senha seja forte (ou seja regenerada).

<?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
fonte
11
Inteligente, mas não permite caracteres duplicados.
Hand-E-Food
11
Em vez de while(true) ... if (condition) breakvocê pode usarwhile (!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-não-destruído;

// 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
fonte
1

Perl, 92

Não é tão conciso quanto a resposta do Ruby, mas tenho certeza de que um assistente de Perl poderia tornar isso ainda mais curto ... Não estou muito feliz com todos os m//s no final, mas parece funcionar e deve satisfazer as condições para eventualmente gerar todas as permutações.

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

Uso da amostra:

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

Editado para corrigir a validação e mudar [[:punct:]]para [\W_]após os comentários dos MvGs.

Dom Hastings
fonte
11
Sua parte de geração é boa, mas seu critério de seleção na condição do loop está completamente errado: por exemplo, uma senha de aaaaaaaaaaaaaafaria o loop terminar. Você deve testar critérios com senhas não aleatórias para garantir que eles façam o que você deseja.
MvG 07/01
Na verdade, você está correto, eu consertei isso e salvei alguns bytes! Obrigado!
Dom Hastings
11
Você tem certeza disso [[:punct:]]? Acho que prefiro o , which is shorter and of which I'm even more sure that it is correct, at least combined with your intervalo '[\ W_] 33..127`.
MvG 07/01
Um bom ponto, acho que fiquei preocupado \Wpor não incluir _, no entanto, você está absolutamente certo, não é necessário: gist.github.com/anonymous/8301237 . Obrigado!
Dom Hastings
1

Java 7 ( 270 234 caracteres)

A premissa é a mesma usada por @assylias com java 8 (gerar senhas aleatórias até uma senha válida). No entanto, em vez de usar lambdas, a senha é gerada iterando uma matriz char e validada pela correspondência de uma 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);
  }
}

Código Minificado:

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
fonte
1

Powershell


Versão One Liner (143 bytes)

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

Mini versão (146 bytes)

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

Versão legível (860 bytes)

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
}

Agradecemos a Iszi por várias dicas para encurtar o código.

Vasili Syrakis
fonte
11
Isso não cobre todas as permutações. Como exemplo, abcd1234ABCD{|}~nunca vai vir para cima porque $symbolas forças, pelo menos um dos símbolos para estar entre ASCII 33 e 47
Mão-E-Food
Dangit! Você deve apontar minha preguiça !? Brincadeirinha ... Eu editei agora. Também fiz com que cada caractere de "requisito" fosse para um índice separado dentro da string, em vez de agrupar os quatro juntos no mesmo índice. Agora, se eu pudesse reduzir isso ...
Vasili Syrakis
Existe alguma razão pela qual você não pode barbear mais alguns personagens encurtando $SR, talvez $Q?
Iszi
Você também deve poder cortar coisas como (g(65..90))as 65..90|g'. And change the instruções down foreach` em foreach-objectloops usando o %alias. Exemplo: foreach($N in (1..11)){... }deve ser factível como 1..11|%{... }. Tenho certeza de que há outras otimizações possíveis, mas na verdade tenho uma implementação completamente diferente em mente que pretendo tentar mais tarde.
Iszi
Dicas legais :) Eu o reduzi para 213 bytes se eu remover os retornos de carro e substituí-los por ponto e vírgula.
Vasili Syrakis
1

Fator, 196 caracteres

Mesmo algoritmo que MvG e moose. Não é o mais curto, mas deve atender a todos os critérios (atuais) da pergunta:

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
fonte
Posso estar interpretando mal a regex, mas acho que algo como ~{}|1234abcdABCDfalhará na regex.
Mão-E-Comida
11
Não, vai funcionar:"~{}|1234abcdABCD" 60 cycle "[A-Z].*[a-z].*[0-9].*[\\W_]" findall empty? not => t
Björn Lindqvist
Eu aceito sua palavra. :-)
Mão-E-Comida
1

C - 154 caracteres

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

Como odeio srand()? Deixe-me contar os caminhos.

Oberon
fonte
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

A sequência impressa possui aspas e escapa os caracteres de barra invertida e de aspas; se isso for inaceitável, printpode ser substituído putStrLnpor mais 3 bytes. Aqui está uma versão mais legível:

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

É bem simples, apenas cria uma lista infinita / lenta de caracteres ASCII aleatórios no intervalo '!'para '~', em seguida, lança o primeiro elemento até que os 15 primeiros caracteres tenham pelo menos um caractere de cada sequência de caracteres necessários.

user3175123
fonte
1

Excel VBA, 209 bytes

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

Gera aleatoriamente 15 caracteres ASCII para que todas as combinações possíveis sejam possíveis. Em seguida, usa um padrão de expressão regular para verificar se ele contém pelo menos um de cada critério.

Se isso acontecer, a senha será exibida, se não "refazer" será exibido.

Agradecemos a Bart Kiers pelo padrão Expressão Regular: https://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char- superior

Wightboy
fonte
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
}

Usando - Basta executar o script

Avi
fonte
0

Python (121 caracteres)

Faz uso do fato de que você pode multiplicar listas em Python [1,2,3] * 2 fornece [1,2,3,1,2,3]. Importa aleatoriamente. Os números em uma lista multiplicada por três são bordas entre os intervalos na tabela ascii para os caracteres necessários, por exemplo, [65, 90] mapeia para letras maiúsculas.

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
fonte
11
"Ele deve ser capaz de gerar todas as permutações de todos os caracteres permitidos." Acho que não, pois os intervalos são sempre aplicados na mesma ordem ...?
Joachim Isaksson
Você está certo, obrigado. Na verdade, eu não percebi que os intervalos devem ser aplicados em ordem aleatória, eles devem ser embaralhados, eu vou editar isso em um momento.
Pawelmhm
Isso precisa ser incluído import randomno código.
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)));

Ou em uma linha (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
fonte