ランダムパスワードジェネレーター


40

ドメインサーバーでは、すべての従業員が次のルールに準拠した強力なランダムパスワードを持っている必要があります。

  • 正確に15文字の長さ。
  • キーボードで入力可能な文字のみ(以下のコードタイプに示すとおり)。ALT + NUMPADコードを使用するように販売を教えることは許可されていません。
  • 少なくとも1つの小文字: abcdefghijklmnopqrstuvwxyz
  • 少なくとも1つの大文字: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • 少なくとも1桁の数字: 0123456789
  • 少なくとも1つのシンボル: `~!@#$%^&*()_+-={}|[]\:";'<>?,./

この目的のために、ITはすべての従業員にランダムパスワードジェネレーターを委託し、配布します。すべての従業員は、ランダムパスワードジェネレーターを使用する必要があります。ランダムパスワードジェネレーターの要件は、上記のパスワード制限に加えて次のとおりです。

  • すべての許容文字のすべての順列を生成できる必要があります。
  • 生成されたパスワードを画面に表示する必要があります。
  • コードはできるだけ小さくする必要があります(バイト単位)。

提案されたソリューションを来週以内に提出してください。


10
あなたはまた、許可されているすべてのパスワードが同じ確率(そうでない場合、私は単に最初の15個のものを、許可された文字と30文字の長いリストを作り、それをシャッフルし、与えることができます)と表示されることを要求すべきである
マーティン・トーマ

@ムース、同意した。新しいルールを追加しました。
ハンドEフード14年

22
ITスタッフを解雇するか、少なくとも教育を強化する必要があります。パスワードをランダムに生成する場合、許可されるパスワードのセットを各カテゴリの少なくとも1文字を含むものに制限すると、実際にはパスワードが弱くなります。許容されるセット。そして、私たちのプログラムは、それをチェックする必要がなければ、はるかに簡単になります。挑戦としては問題ありません。
MvG 14年

10
@MvG確かに:correcthorsebatterystaple
ジョナ

1
すべてのパスワードが生成可能であることを要求することで、@ mooseに実際には答えていません。それらは等しい確率で現れるはずです。
イーサンボルカー

回答:


29

Mathematica(18)

ちょっとチートさせて

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

PSは安全ではありません:)


6
コードはどこにありますか?
DavidC 14年

11
それは、各文字クラス要件の少なくとも1つを満たすことが保証されていますか?
ハンドEフード14年

3
@ Hand-E-Foodはい、そうです!解釈を見ると、パスワードの長さ15、必要な小文字、大文字が必要、数字が必要、特殊文字が必要です。
イベルトゥコフ14年

6
+1賢い、しかし卑劣。
DavidC 14年

10
Mathematicaにはすべての機能があることは知っていましたが、これは
コンラッドボロスキー14年

13

ルビー、74 69バイト

ASCIIの範囲33〜126からランダムにサンプリングし、すべてのクラスのキャラクターが存在するようにします。

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

ルビー、39バイト

ムースの巧妙な発見を使用して:

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

モブを満たすように編集します。

最初にこれを投稿したにルールが変更されことに注意してください。その時点で、前の両方のエントリがルールに適用されました。また、ルールがまだあまり明確に定義されていないことを指摘したいと思います。

(..)すべての許容文字のすべての順列

「順列」。許容文字セットの順列は、許容文字セット自体と同じ長さであるため(パスワードは15文字と想定されています)、残りのルールに適合する許容文字の順列はありませんそして、順列には繰り返しはありません。しかし、私の最初のエントリは、ここで他の多くの賛成の答えよりもまだ「ランダム」です。

それにもかかわらず、ここにあります。文字とアンダースコアの繰り返しを許可します。

ルビー、77バイト

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

「引用符」で囲まれた文字列と一部の文字がバックスラッシュでエスケープされているため、このputs代わりに使用しました。pp

ルビー、70バイト

Venteroが指摘して~いるように、正規表現の前でスキップでき、printを置き換えることができputs$_ます。しかし、このい出力では、拒否されたパスワードもすべて印刷し、それを1行に絞ります。

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

説明

要求どおり。$_は、入力から読み取られた最後の行を含む半魔法の変数です。したがって、このように、常に保存する必要はありません。ただし、ここでは別のプロパティ、つまり~演算子が正規表現を直接適用するために使用します。これは、chronによって最初に学んだトリックです。の使用法を置き換えましたallが、残りを取得すれば理解しやすいはずです(ドキュメントを参照)。


2
コードについて少し説明していただけますか?何を.all?{|r|~r}するの?何を$_=するの?
マーティントーマ14年

3
サンプル行は巧妙ですべてですが、「許容されるすべての文字のすべての順列を生成できなければならない」ことに違反していると思います。文字に関する限り、パスワードに広告のみを含めることができるとはどこにも書かれていません。zが許可されている文字である場合、zがパスワードに含まれている可能性が> 0である必要があります。
nitro2k01 14年

1
\WRubyでは、アンダースコアが含まれますか_?ほとんどの正規表現方言では、そうではないことを知っています。また、コードで_英数字以外の記号が1つだけのパスワードを生成できなかった場合、1つの要件に違反することになります。2番目のアプローチは明らかにその要件に違反していますが、その時点では正しく表現されていなかったと思います。
MvG 14年

1
@MvG:そのとおりです。\WPerl互換のRegEx(source)にはアンダースコアが含まれていません。
マーティントーマ14年

1
さらに、あなたのソリューションは@mooseとPythonで私が抱えていた同じ問題の影響を受けます:sample要素を繰り返さないため、繰り返される要素を持つパスワードをコードで生成することはできません。Wolfram Alphaを除いて、あなたのソリューションがどのように主要なソリューションであるかを見て、あなたが従い、まだリードを維持できるかどうかを見るのはいいことです。そんなに難しくないはずです。
MvG 14年

12

Java 8-354 329 319 275 267文字

楽しみのために、Java 8でラムダを使用します-可能性のある各出力は、同じ確率で検出されます。

許可された文字には33から126までの連続したASCIIコードがあるという事実を使用します。

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

サンプル出力:

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

圧縮プログラム:

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


どの程度while(a+A+d+p<4)とともにa|=1代わりのa++?または、ビットマスク、つまりasループ条件のようなa|=1through a|=8などを使用a<15します。正しく数えた場合、これによりさらに13文字が節約されます。
MvG 14年

@MvGの良い点-同様のことをして、私は信じているいくつかの余分な文字を節約しました。
assylias

@MvGそしてを使用すると、new String(int[],int,int)さらに40奇数の文字が節約されます!
assylias

8

Python 2.X + 3.X(229文字):生成および置換

アイディア

  1. 最初に15個の許可されたシンボルのリストを作成します
  2. ランダムな位置rをランダムな数字で置き換える
  3. ランダムな位置をs、でs != r大文字に置き換えます
  4. 小文字と記号についても2および3と同じです。

コード

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文字):生成および確認

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)
  • Python正規表現には存在しないと言ってくれたMvGに感謝します。\u\l
  • grcのおかげで、random.sample交換なしであると教えてくれたので、交換でサンプリングする必要があるすべての許可されたパスワードを取得してください。

問題の説明での欠陥の使用

現在、問題の説明では、すべての記号/数字が同じ確率で表示されることを要求していません。次の解決策では、単一のシンボルや位置について推測することはできません。しかし、あなたは複数のものでそれを行うことができます。

Python 2.X + 3.X(62文字)

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

サンプルを使用するアイデアをくれたdanieroに感謝します。


欠陥を見つけるのは非常にスムーズです!私はそれをプラグインしましたが、それを識別するためのボーナスポイント。:-)
Hand-E-Food 14年

あなたのgen&checkは私のアプローチに似ています。好奇心から:これはどこにあり\lますか?それを見ないでください参照。私のPython 3.3.3は受け入れさえしません"\u"str(…)3.3.3または2.7.6のいずれかの文字に参加していません。optmizationのための1つの提案:all(s("\\"+i,p)for i in "dluW")
MVG

random.sample置換せずに要素を選択するため、すべてのパスワードが使用できるわけではありません。
GRC

@MvG:ありがとう。私はそれを見たばかりで\u\lvimのみです。
マーティントーマ14年

7

* 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

正しく機能するに$aは、有効であるがランダムではないパスワードを事前に設定しないでください。含めたい場合a=、行を前に分割すると、さらに3文字になりますが、繰り返し実行できます。もちろん、すべての改行を置き換えることもできる;ため、ワンライナーを使用して、何度でも実行できます。

さらに、あなたが設定されている必要がありますLC_ALL=Cまたは任意のロケール固有の環境変数を設定します(ないLANGLC_CTYPE文字範囲はASCII順に等しい照合順序に依存するため、特に)。

/dev/urandomランダムバイトのソースです。!-~質問で指定されているすべての許容文字の範囲です。次の引数にリストされていないtr -dcすべての文字を削除します。残りの15文字を受け取ります。必要な種類のそれぞれが少なくとも1回発生するかどうかを確認します。その入力は候補の4つのコピーで構成されているため、記号の順序は重要ではないため、すべての可能なパスワードが選択される可能性があります。grepを抑制し、出力します。headgrep-q

理由は不明ですが、/dev/random代わりに/dev/urandom年齢がかかります。エントロピーはすぐに使い果たされたようです。に入れば、もう少しバイトを避けることができますcd/dev、それはごまかしのように感じます。

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

コードを読みやすくするために、ループの後に改行とインデントを追加しましたが、これは必要ではなく、カウントしませんでした。

これは、bashバージョンと本質的に同じ考えです。ここでのランダムなソースはrandom.sample、要素を繰り返しません。この事実に対抗するために、許容される文字のリストのコピーを15個使用します。こうすることで、すべての組み合わせが引き続き発生しますが、文字が繰り返される組み合わせはあまり発生しません。しかし、この質問はすべての順列に対して等しい確率を必要とせず、可能性のみを必要としたため、これをバグではなく機能と見なすことにしました。

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)

1つの改行と1つのインデントが再びカウントされません。いくつかのPython 3固有の構文オーバーヘッドを除けば、これは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)

読みやすくするために改行を追加しましたが、カウントしませんでした。

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

ループ内の改行とインデントが追加されましたが、カウントされません。気が;向いたら、これを再び単一の区切り行に移動できます。


ハ!私はあなたがgreplあなたのRコードで使用できたと指摘しようとしていました。テストパスワードを4回繰り返すことで、すべてのチェックを1回で実行できると考えた場合に限ります。そして、あなたが知っている、もし私が考えていたsampleとしたらintToUtf8。ただし、すべての可能なパスワードを取得するために、サンプルメソッドにreplace=TRUE追加する必要があります(より簡潔には、追加する必要があります)。,T
AmeliaBR 14年

@AmeliaBR:あなたは正しい、そのreplace=T間違いを修正した、これを指摘してくれてありがとう。intToUtf8タブ補完で可能性のある名前を推測して見つけるには、かなり時間がかかりました。そのような関数が存在しなければならないことは知っていましたが、などのより一般的な名前chrは使用されませんでした。
MvG 14年

@MvG:Pythonコードが終了する理由がまったくわかりません。なぜそれが必要なのです*4か?私はあなたの正規表現がどんな文字列にもマッチすると思いました、その広告は最初に大文字、次に何か、次に小文字、何よりも...私は何が間違っていましたか?
マーティントーマ14年

@moose:お気づきのとおり、私の正規表現は特定の順序で必要なカテゴリをチェックします。しかし、現在の候補者の4つのコピーを連結することで、順序が問題にならないようにすることができます。パスワードの後ろに数字、数字、小文字、大文字の記号が含まれている場合でも、一致するものがあります。一致が失敗する唯一の方法は、カテゴリが完全に欠落している場合です。また、私はre.searchそうre.matchではないことに注意してください。したがって、正規表現は候補パスワードのどこにでも一致する可能性があります。これは、最終的に終了する理由を説明していますか?
MvG 14年

ああ、私はあなたがのre.search代わりに使用することに気づきませんでしたre.match。それで説明できます。しかし、私はまだあなたが必要ないと思います*4。説明をありがとう(+1)
マーティントーマ14年

7

C#(123-139 103-127文字圧縮):

で完全に適切なフレームワークメソッドを使用しSystem.Web.dllます。

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

コンパクト化:

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

例:

b+m2ae0K:{dz7:A

または、int numberOfNonAlphanumericCharactersコマンドラインから2番目のパラメーター()の値を取得します。

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

3
GeneratePassword質問で指定された記号の完全なセットをサポートしていません。また、各文字カテゴリの最小出現回数に関する保証も見つかりませんでした。
MvG 14年

2
class Pとを使用してさらに圧縮できstring[] aます。
d3dave

@MvG、それは面白いです。フランス語などの言語でアクセント記号付き文字を書くために一般的に使用される記号は除外されているようです。おそらく賢い動きです。パスワードを使い果たすには、キーボードの言語を変更するだけで十分です。
Hand-E-Food 14年

5

R(301 322文字)

修正は、数字の確認を忘れていました。

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

(明確にするために空白が追加されています)。

94文字のすべての可能な15文字の順列を生成します。次に、基準に一致するまでランダムに1つを選択します。

魔法は 、最初のリストのすべての因子と2番目のリストのすべての因子の相互作用でq:qある新しい因子データ型を生成する操作にあります。その要因のレベル」。許可された文字のリストの15個のコピーを操作すると、可能なレベル(94 ^ 15)が得られます。q

自宅でこれを試さないでください。コードが3文字の順列をすべて把握するのに数秒かかります。コンピューターのメモリが不足しなかった場合、15文字のすべての順列を把握するのにかかる時間は想像できません。その間。完成した(3文字のパスワード)スクリプトを実行して確認したとき、最初に出力されたパスワードは "oO ="でした。これは、このコードに対する反応をまとめたものだと思います。


@MvGには、はるかに実用的ではるかに短いRスクリプトがありますが、それほど素晴らしいものではありません:codegolf.stackexchange.com/a/17700/12413
AmeliaBR

それにもかかわらず、私はあなたのアイデアが好きです。私が見た多くのコードゴルフスニペットは、言語の特定の機能に苦労させました。そして、あなたのコードは確かにそれらの相互作用でRのためにそれをします。
MvG 14年

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]

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

問題の説明では必要ないため、結合を削除すると9桁少なくなります。スペースを削除することで、さらに2つ少なくなります。
マーティントーマ14年

@mooseあなたがコメントする直前にスペースを削除しました:-)私はjoinちょっとそこにいる必要があると感じています:ユーザーは出力からPythonリストの構文を理解することが期待されます['q', 'u', ...]か?
ジョナサンラインハルト14年

1
印刷物を削除することを考えました。バイト単位のサイズが重要な場合、それらはパンチカード時間内にある可能性があります。そうすれば、彼らはそれを見るだけでメモリを読むことができるかもしれません。または、彼らは「本物のプログラマー」です:xkcd.com/378
マーティントーマ

1
コードを正しく読んでいる場合、これはすべての順列要件を満たしていません。常に12文字の小文字が使用され、他のグループ(などaA$bc1111111111)が複数あるパスワードは不可能になります。
IQAndreas

1
ジョナソンの弁護では、彼の投稿の5分後に順列規則が追加されたと思います。
ハンドEフード14年

4

Golfscript(60)

obl以来。golfscriptがありませんし、初心者としてはとにかく練習が必要です:)

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

必要な4つの文字と11のランダムな文字で配列を作成し、ランダムな順序で並べ替えます。


+1 {r}$。それはリストをシャッフルするかなり汚い方法です-私はそれが好きです!;-)
イルマリカロネン14年

...しかし、私はこれが例えばを出力できるとは思わない0Aa~~~~~~~~~~~~。:-(
イルマリカロネン14年

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

ルールの使用:

function(x){return x*x}として書き換えることができますfunction(x)x*x。値を返す関数でのみ機能するようです。

減少次の反復、x.sort(function().5-R())x.sort(y=>.5-R())

次のイテレーションは、太い矢印表記でさらに縮小されました。これは、残念ながらFirefox 22以降でのみ機能します。


素晴らしい圧縮!:D
IQAndreas 14年

2

JavaScript(269文字の圧縮)

明確にするために、これは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("");

ここでは、269文字に圧縮されています(その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

shuffle()「カスタム機能」とはどういう意味ですか。JavaScriptの一部ですか、それとも自分で作成する必要があるコードですか?
Hand-E-Food 14年

@ Hand-E-Food私はそれがJavaScriptに組み込まれていないことを意味し、ここの開発者は配列をシャッフルする方法を知っているはずなので、コードに関数を含める必要はないと感じました。ただし、JS-Fiddleで使用できます(16行目)。
IQAndreas

1
私のポイントは、それはあなたのバイトカウントにカウントされるということです。しかし、今ではあなたはそれを圧縮バージョンで実装していると思うので、無視してください。:-)
Hand-E-Food 14年

2

クロージュア(63):

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

ただし、各カテゴリ(上、下、数字、記号)の少なくとも1文字が含まれるように改善する必要があります。


2

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)

実際の動作を見る-1

アクションで見る-2


1
最後の行を追跡するのに問題がありますが、コードはすべての順列要件を満たしているようには見えません。
IQAndreas

コードは~0Aa、で始まるパスワードを生成したり、bが続くパスワードを生成したりしませんa
ハインジ14年

@Heinzi:はい、私はすべての順列が必要であることに同意しますrは考慮されず、a ... z、A..Z、0..9、!... + :(。 ..
vhadalgi 14年

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=

コメント/インデント:

%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

Gofled Code

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

ゴルフとコメントなし

# 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

この正規表現は、これをわずかに短くする可能性があると思います:^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$、これで1つの一致を実行できます。これは、Upper、Lower、Digit、Symbolが1つある場合にのみ一致します。
ヴァシリシラキス14年

@VasiliSyrakisわかりました、あなたはそれを少し通り抜けなければならないかもしれません。しばらく時間がかかると思われる場合は、チャットルームを自由に開始してください。私が混乱しているいくつかの事柄:1.)そこに含まれている15番を見る。文字列が正確に15文字であることを確認するためですか?その場合、スクリプトは当然15文字の文字列のみを生成するため、これは省略できます。2.)「上、下、数字、記号が1つある場合にのみ一致します」とはどういう意味ですか?それは、それぞれが正確に 1つ、または少なくとも 1 つが存在する場合にのみ一致することを意味しますか?前者は物事を壊します。
イッツィ14年

また、RegExは文字の順序を無視しますか?たとえば、4文字の文字列と一致するように調整されている場合、両方1aZ%(p3R一致しますか?オンラインでそれを行う方法を見つけるのに苦労しました。
イッツィ14年

現在のスクリプトからの出力に対して新しいRegExをテストしました。それほど信頼できるとは思えません。コード:$x-cmatch'^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$'良い一致:C>suD1?hTwbDx(z j%4O]HyeG|u[U$5 O/rGeD0$hJk=GO/失敗した一致:3evthX3_X^nBrR` .nA〜uYzrR4YV-r.`u-IjZE48ntQ;HxV
Iszi

チャットルームを開くにはどうすればよいですか?
ヴァシリシラキス14年

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

より読みやすい(実行可能ではない)方法で記述されています。

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

かなり単純で、驚くべきことに、「生成、一致失敗時の再試行」バージョンよりも長くはありません。


これにより、たとえば、以下を含むすべての適格なパスワードが実際に生成されます0Aa~~~~~~~~~~~~か?(ことに注意してください'~' == chr(126)。)
イルマリカロネン14年

1

PSQL(189)

PSQLは少し冗長であるように感じます... :)

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

SQLfiddleデモ


1

PHP、235 225

このスクリプトは文字をシャッフルし、その後RegExを介してチェックしてパスワードが強力であること(または再生成されること)を確認します。

<?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
賢いですが、重複文字は許可されません。
Hand-E-Food 14年

1
代わりにwhile(true) ... if (condition) break使用することができますwhile (!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(''))

セミゴルフなし;

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

Rubyの答えほど簡潔ではありませんが、Perlウィザードでこれをさらに短くすることができると確信しています...私はm//最後にすべてに満足していませんが、うまくいくようで、最終的に生成するための条件を満たす必要がありますすべての順列。

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

サンプル使用法:

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

検証を修正[[:punct:]][\W_]、MvGsコメントの後に変更するように編集されました。


1
生成部分は素晴らしかったが、ループ条件での選択基準は間違いです。たとえば、パスワードaaaaaaaaaaaaaaがの場合、ループが終了します。ランダムでないパスワードを使用して基準をテストし、希望どおりに動作することを確認する必要があります。
MvG 14年

確かに、あなたは正しいです、私はこれを修正し、いくつかのバイトを節約しました!ありがとう!
ドムヘイスティングス14年

1
これについて確か[[:punct:]]ですか?「[\ W_] , which is shorter and of which I'm even more sure that it is correct, at least combined with your 33..127」の範囲を好むと思います。
MvG 14年

良い点\W_、含まれていないことを心配していたと思いますが、絶対に正しい、それは必要ありません:gist.github.com/anonymous/8301237。ありがとうございました!
ドムヘイスティングス14年

1

Java 7(270 234文字)

前提は、Java 8で@assyliasが使用するものと同じです(有効なパスワードまでランダムパスワードを生成します)。ただし、ラムダを使用する代わりに、char配列を反復することでパスワードが生成され、正規表現に一致することで検証されます。

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

縮小コード:

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

パワーシェル


ライナーバージョン(143バイト)

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

ミニバージョン(146バイト)

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

読み取り可能なバージョン(860バイト)

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
}

コードを短縮するためのさまざまなヒントをIsziに与えてください。


1
これはすべての順列をカバーするわけではありません。例として、少なくとも1つの記号がASCII 33と47の間にあるabcd1234ABCD{|}~ため、決して表示されません。$symbol
Hand-E-Food 14年

ダンギット!私の怠inessを指摘してください!?冗談です...今編集しました。また、同じ「インデックス」で4つをまとめて詰め込むのではなく、各「要件」文字を文字列内の個別のインデックスに移動させました。今...私はこれを短縮することができる唯一の場合
Vasili Syrakis

に短縮$SRすることで、さらに数文字を剃ることができない理由はあります$Qか?
イッツィ14年

また、エイリアスを使用(g(65..90))して65..90|g'. And change the foreach`ステートメントのようなものをforeach-objectループにカットできる必要があります%。例:foreach($N in (1..11)){... }は... として実行可能でなければなりませ1..11|%{}。可能な他の最適化もあると確信していますが、実際には完全に異なる実装を念頭に置いており、後で試すことを計画しています。
イジ14年

素敵なヒント:)改行を取り出してセミコロンに置き換えると、213バイトに短縮されました。
ヴァシリシラキス14年

1

ファクター、196文字

MvGおよびムースと同じアルゴリズム。これは最短ではありませんが、質問のすべての(現在の)基準を満たす必要があります。

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

私は正規表現を誤解しているかもしれませんが、そのようなもの~{}|1234abcdABCDは正規表現に失敗すると思います。
Hand-E-Food 14年

1
いいえ、動作しません:"~{}|1234abcdABCD" 60 cycle "[A-Z].*[a-z].*[0-9].*[\\W_]" findall empty? not => t
ビョルンリンドクヴィスト14年

あなたの言葉を受け取ります。:-)
Hand-E-Food 14年

1

C-154文字

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

どうやって嫌いsrand()ですか?方法を数えてみましょう。


1

ハスケル、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

印刷された文字列には引用符があり、バックスラッシュと引用文字をエスケープします。それが受け入れられない場合は、さらに3バイトでprint置き換えることができputStrLnます。より読みやすいバージョンは次のとおりです。

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

それは非常に簡単で、範囲'!'から範囲内のランダムなASCII文字の無限/遅延リストを作成し'~'、最初の15文字が必要な文字の各文字列から少なくとも1文字になるまで最初の要素を捨てます。


1

Excel VBA、209バイト

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

15個のASCII文字をランダムに生成するため、可能なすべての組み合わせが可能です。次に、正規表現パターンを使用して、各基準が少なくとも1つ含まれているかどうかを確認します。

存在する場合はパスワードが表示され、存在しない場合は「やり直し」が表示されます。

正規表現パターンのBart Kiersの功績:https ://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char- アッパー


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
}

使用 -スクリプトを実行するだけ


0

Python(121文字)

Python [1,2,3] * 2でリストを乗算できるという事実を利用して、[1,2,3,1,2,3]を与えます。ランダムにインポートします。リスト内の数字に3を掛けたものは、必要な文字のASCIIテーブルの範囲間の境界線です。たとえば、[65、90]は大文字にマップされます。

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
「すべての許容文字のすべての順列を生成できる必要があります。」範囲は常に同じ順序で適用されるので、それはそうではないと思います...?
ヨアヒムイザクソン14年

あなたは正しい、ありがとう。確かに、範囲がランダムな順序で適用されるべきであることに気づかず、それらはシャッフルされるべきです。すぐに編集します。
パヴェルムフ14年

これは実際にimport randomコードに含める必要があります。
メゴ

0

PHP 5.5(230バイト)

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

または1行(211バイト)

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)));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.