เครื่องสร้างรหัสผ่านแบบสุ่ม


40

เซิร์ฟเวอร์โดเมนต้องการให้พนักงานทุกคนมีรหัสผ่านแบบสุ่มที่รัดกุมและสอดคล้องกับกฎต่อไปนี้:

  • ยาว 15 ตัวอักษร
  • อักขระที่พิมพ์ได้บนแป้นพิมพ์เท่านั้น (ดังแสดงในรหัสประเภทด้านล่าง) ไม่อนุญาตให้สอนการขายเพื่อใช้รหัส ALT + NUMPAD
  • อย่างน้อย 1 ตัวอักษรพิมพ์เล็ก: abcdefghijklmnopqrstuvwxyz
  • อย่างน้อย 1 ตัวอักษรตัวพิมพ์ใหญ่: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • ตัวเลขอย่างน้อย 1 หลัก: 0123456789
  • อย่างน้อย 1 สัญลักษณ์: `~!@#$%^&*()_+-={}|[]\:";'<>?,./

เพื่อจุดประสงค์นี้ฝ่ายไอทีได้มอบหมายและจะแจกจ่ายตัวสร้างรหัสผ่านแบบสุ่มให้กับพนักงานทุกคน พนักงานทุกคนจะต้องใช้เครื่องสร้างรหัสผ่านแบบสุ่ม ข้อกำหนดสำหรับตัวสร้างรหัสผ่านแบบสุ่มคือนอกเหนือจากข้อ จำกัด รหัสผ่านด้านบน:

  • จะต้องสามารถสร้างการเรียงสับเปลี่ยนทั้งหมดของอักขระที่อนุญาตทั้งหมด
  • มันจะต้องแสดงรหัสผ่านที่สร้างขึ้นบนหน้าจอ
  • รหัสจะต้องมีขนาดเล็กที่สุดเท่าที่เป็นไปได้ (เป็นไบต์)

โปรดส่งโซลูชันที่เสนอของคุณภายในสัปดาห์หน้า


10
คุณควรเรียกร้องให้รหัสผ่านทั้งหมดที่ได้รับอนุญาตมีความน่าจะเป็นแบบเดียวกัน (ไม่เช่นนั้นฉันสามารถสร้างรายชื่อยาว 30 ตัวอักษรโดยใช้ตัวอักษรสับเปลี่ยนและให้รหัส 15 ตัวแรก)
Martin Thoma

@ ตกลง, ตกลง ฉันได้เพิ่มกฎใหม่
Hand-E-Food

22
คนไอทีควรถูกไล่ออกหรืออย่างน้อยก็มีการศึกษาที่ดีกว่า: หากคุณสร้างรหัสผ่านแบบสุ่มให้ จำกัด ชุดรหัสผ่านที่อนุญาตให้ใช้กับรหัสผ่านที่มีอักขระอย่างน้อยหนึ่งตัวในแต่ละหมวดหมู่ซึ่งจะทำให้รหัสผ่านอ่อนแอลงชุดที่อนุญาต และโปรแกรมของเราจะง่ายขึ้นมากถ้าเราไม่ต้องตรวจสอบว่า ... ตกลงไม่ต้องแก้ไขการแข่งขันหลังจากที่มีผู้ส่งเข้ามาจำนวนมาก มันเป็นเรื่องที่ท้าทาย
MvG

10
@MvG แน่นอน:correcthorsebatterystaple
Jonathon Reinhart

1
คุณยังไม่ได้ตอบ @moose โดยกำหนดให้รหัสผ่านทั้งหมดสามารถใช้งานได้ ควรปรากฏด้วยความน่าจะเป็นที่เท่ากัน
Ethan Bolker

คำตอบ:


29

Mathematica (18)

ให้ฉันโกงหน่อย

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

PS ไม่ปลอดภัย :)


6
รหัสอยู่ที่ไหน
DavidC

11
สิ่งนี้รับประกันได้หรือไม่ว่าจะเป็นไปตามข้อกำหนดของตัวละครอย่างน้อยหนึ่งตัว ?
Hand-E-Food

3
@ Hand-E-Food ใช่มันเป็น! หากคุณดูการตีความที่คุณจะเห็น: ความยาวรหัสผ่าน 15, ตัวอักษรตัวพิมพ์เล็กจำเป็นต้องใช้, ตัวอักษรตัวพิมพ์ใหญ่จำเป็นต้องใช้ตัวเลข, ตัวอักษรพิเศษที่จำเป็น
ybeltukov

6
+1 ฉลาด แต่ลับๆล่อๆ
DavidC

10
ฉันรู้ว่า Mathematica มีฟังก์ชั่นสำหรับทุกสิ่ง แต่นี่คืออะไร?
Konrad Borowski

13

Ruby, 74 69 ไบต์

เพียงแค่สุ่มตัวอย่างจากช่วง ascii 33 - 126 จนกระทั่งมีคลาสของตัวละครทั้งหมด:

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

Ruby, 39 ไบต์

ใช้การค้นพบที่ฉลาดของมูส:

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

แก้ไขเพื่อตอบสนองม็อบ:

โปรดทราบว่ากฎมีการเปลี่ยนแปลงหลังจากที่ฉันโพสต์นี้เป็นครั้งแรก ในเวลานั้นทั้งรายการก่อนหน้านี้นำไปใช้กับกฎ ฉันอยากจะชี้ให้เห็นว่ากฎยังไม่ชัดเจนเกินไป:

(.. ) การเรียงสับเปลี่ยนทั้งหมดของอักขระที่อนุญาตทั้งหมด

"พีชคณิต" ขณะนี้ไม่มี การเปลี่ยนลำดับของตัวอักษรที่อนุญาตที่สอดคล้องกับส่วนที่เหลือของกฎเพราะการเปลี่ยนแปลงของชุดของตัวละครที่อนุญาตใด ๆ ตราบเท่าที่ชุดของตัวละครที่อนุญาตเอง (ในขณะที่รหัสผ่านควรจะเป็น 15 ตัวอักษรยาว) และไม่มีการทำซ้ำในการเปลี่ยนแปลง อย่างไรก็ตามรายการแรกของฉันยังคง "สุ่ม" มากกว่าคำตอบ upvoted อื่น ๆ ที่ดีที่นี่

อย่างไรก็ตามที่นี่คุณมีมัน อนุญาตการซ้ำของอักขระและขีดล่าง:

Ruby, 77 ไบต์

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

ฉันยังใช้putsแทนpในอันนี้เพราะpพิมพ์สตริงที่อยู่ใน "เครื่องหมายคำพูด" และตัวละครบางตัวหนีด้วยแบ็กสแลช

Ruby, 70 ไบต์

เป็นจุด Ventero ออก~สามารถข้ามในด้านหน้าของ regexes และสามารถแทนที่print puts$_แต่ด้วยการส่งออกที่น่าเกลียดนี้เป็นสาเหตุที่คุณอาจพิมพ์รหัสผ่านที่ถูกปฏิเสธทั้งหมดด้วยเช่นกันบีบลงในหนึ่งซับ:

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

คำอธิบาย

ตามที่ขอ. $_เป็นตัวแปรกึ่งเวทที่มีบรรทัดสุดท้ายที่อ่านจากอินพุตดังนั้นคุณไม่จำเป็นต้องเก็บมันไว้เช่นนี้เสมอไป นี่ แต่เราใช้มันเพราะทรัพย์สินของผู้อื่นคือว่า~ผู้ประกอบการมีผลบังคับใช้ regex โดยตรงกับมัน, เคล็ดลับแรกที่ผมได้เรียนรู้โดยChron ฉันแทนที่การใช้งานของallแต่มันควรจะค่อนข้างเข้าใจง่ายถ้าคุณได้รับส่วนที่เหลือ ( ดูเอกสาร )


2
คุณช่วยอธิบายรหัสของคุณหน่อยได้ไหม? อะไร.all?{|r|~r}ทำอย่างไร อะไร$_=ทำอย่างไร
Martin Thoma

3
บรรทัดตัวอย่างนั้นฉลาดและทั้งหมด แต่ฉันคิดว่ามันละเมิด "ต้องสามารถสร้างการเรียงสับเปลี่ยนทั้งหมดของอักขระที่อนุญาตทั้งหมด" มันไม่มีที่ไหนบอกว่ารหัสผ่านอาจมีโฆษณาเท่าที่ตัวอักษรมีความกังวล หาก z เป็นอักขระที่อนุญาตควรมีโอกาส> 0 ที่ z อยู่ในรหัสผ่าน
nitro2k01

1
ไม่\Wในรูบีรวมถึงขีด_? ในภาษาถิ่น regex ส่วนใหญ่ฉันรู้ว่ามันไม่ได้ และหากรหัสของคุณไม่สามารถสร้างรหัสผ่านที่มี_เพียงสัญลักษณ์เดียวไม่ใช่ตัวเลขและตัวอักษรก็จะละเมิดข้อกำหนดหนึ่ง วิธีที่สองเห็นได้ชัดว่าละเมิดข้อกำหนดนั้น แต่ฉันคิดว่ามันไม่ได้ถูกใช้อย่างถูกต้องในเวลานั้น
MvG

1
@MvG: ถูกต้อง \Wไม่มีขีดล่างใน RegEx ที่เข้ากันได้กับ Perl ( ต้นฉบับ )
Martin Thoma

1
นอกจากนี้โซลูชันของคุณจะได้รับผลกระทบจากปัญหาเดียวกัน @moose และฉันมีกับ Python: sampleไม่ทำซ้ำองค์ประกอบดังนั้นรหัสของคุณกับรหัสซ้ำไม่สามารถสร้างขึ้นได้โดยรหัสของคุณคุณสามารถแก้ไขปัญหาทั้งสองนี้ได้หรือไม่ การเห็นว่าคุณเป็นวิธีแก้ปัญหาชั้นนำได้อย่างไรยกเว้น Wolfram Alpha มันจะเป็นการดีถ้าได้เห็นว่าคุณสามารถทำตามและยังคงเป็นผู้นำได้หรือไม่ ฉันเดาว่ามันไม่ควรยากเกินไป
MvG

12

Java 8 - 354 329 319 275 267 ตัวอักษร

เพื่อความสนุกสนานการใช้ lambdas กับ Java 8 - แต่ละเอาต์พุตที่เป็นไปได้มีความน่าจะเป็นเหมือนกัน

มันใช้ความจริงที่ว่าตัวละครที่ได้รับอนุญาตมีรหัส ascii ต่อเนื่องกันจาก 33 เป็น 126

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

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

ตัวอย่างผลลัพธ์:

.*;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++? หรือใช้ bitmasks เช่นสิ่งของa|=1ผ่านโดยa|=8มีa<15เงื่อนไข loop นี่จะบันทึกอีก 13 ตัวอักษรถ้าฉันนับอย่างถูกต้อง
MvG

@MGG จุดที่ดี - ทำสิ่งที่คล้ายกันประหยัดสองตัวอักษรพิเศษฉันเชื่อว่า
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)
  • ขอขอบคุณที่MVGที่บอกว่า\uและ\lไม่ได้อยู่ในหลาม regex
  • ขอบคุณgrcที่บอกฉันว่าrandom.sampleไม่มีการเปลี่ยนเป็นไปได้ที่จะได้รับรหัสผ่านที่เป็นไปได้ทุกครั้งที่เราจำเป็นต้องมีการสุ่มตัวอย่างด้วยการเปลี่ยน

การใช้ข้อบกพร่องในคำอธิบายปัญหา

ปัจจุบันคำอธิบายปัญหาไม่ต้องการให้ทุกสัญลักษณ์ / ตัวเลขปรากฏขึ้นพร้อมความน่าจะเป็นเดียวกัน ด้วยวิธีแก้ไขปัญหาต่อไปนี้คุณไม่สามารถทำการสันนิษฐานเกี่ยวกับสัญลักษณ์และ / หรือตำแหน่งเดียวได้ แต่คุณสามารถทำได้หลายอัน

Python 2.X + 3.X (62 ตัวอักษร)

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

ขอบคุณ daniero สำหรับแนวคิดในการใช้ตัวอย่าง


การหาข้อบกพร่องราบรื่นมาก! ฉันเสียบปลั๊กอันนั้น แต่คะแนนโบนัสสำหรับการระบุ :-)
Hand-E-Food

Gen & Check ของคุณคล้ายกับแนวทางของฉัน ออกจากความอยากรู้: สิ่งนี้อยู่ที่ไหน\lและอื่น ๆ สำหรับงูหลาม regexes เอกสาร ไม่เห็นมันในการอ้างอิง Python ของฉัน 3.3.3 จะไม่ยอมรับ"\u"เลย The str(…)ไม่ได้เข้าร่วมตัวอักษรใน 3.3.3 หรือ 2.7.6 หนึ่งในข้อเสนอแนะสำหรับ all(s("\\"+i,p)for i in "dluW")optmization:
MvG

random.sampleเลือกองค์ประกอบโดยไม่ต้องเปลี่ยนดังนั้นจึงไม่สามารถใช้รหัสผ่านทั้งหมดได้
grc

@MvG: ขอบคุณ ฉันเพิ่งเห็นมัน\uและ\lเป็นเสียงเรียกเข้าเท่านั้น
Martin Thoma

7

Bash on * ระวัง (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=และแยกแถวหน้านั่นคือตัวละครอีกสามตัว แต่มันก็ช่วยให้คุณสามารถทำสิ่งนั้นซ้ำ ๆ ได้ เห็นได้ชัดว่าคุณสามารถแทนที่บรรทัดใหม่ทั้งหมดด้วย;เพื่อให้คุณมีหนึ่งซับซึ่งคุณสามารถดำเนินการได้บ่อยเท่าที่คุณต้องการ

นอกจากนี้คุณควรตั้งค่าLC_ALL=Cหรือไม่ตั้งค่าตัวแปรสภาพแวดล้อมเฉพาะโลแคล ( LANGและLC_CTYPEโดยเฉพาะ) เนื่องจากช่วงอักขระขึ้นอยู่กับลำดับการเรียงจะเท่ากับลำดับ ascii

/dev/urandomเป็นแหล่งของการสุ่มไบต์ !-~คือช่วงของอักขระที่อนุญาตทั้งหมดตามที่ระบุในคำถาม tr -dcลบอักขระทั้งหมดที่ไม่ได้ระบุไว้ในอาร์กิวเมนต์ถัดไป headใช้เวลา 15 ตัวอักษรที่เหลือ grepตรวจสอบว่าแต่ละชนิดที่ต้องการเกิดขึ้นอย่างน้อยหนึ่งครั้งหรือไม่ ข้อมูลที่ป้อนประกอบด้วยสำเนาสี่ชุดของผู้สมัครดังนั้นลำดับของสัญลักษณ์จึงไม่สำคัญดังนั้นรหัสผ่านที่เป็นไปได้ทั้งหมดจึงมีโอกาสในการเลือก -qที่จะไม่ใส่ grep เอาท์พุท

ด้วยเหตุผลที่ไม่รู้จัก/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

ในการทำให้โค้ดอ่านได้ฉันได้เพิ่มบรรทัดใหม่และการเยื้องหลังลูปที่ไม่จำเป็นและฉันไม่ได้นับ

นี่เป็นหลักความคิดเดียวกับในเวอร์ชั่นทุบตี แหล่งสุ่มนี่คือ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)

หนึ่งบรรทัดใหม่และอีกหนึ่งการเยื้องไม่นับ นอกเหนือจากค่าใช้จ่ายเฉพาะของ Python-3 บางส่วนของไวยากรณ์นี้เป็นโซลูชั่นเดียวกันสำหรับ Python 2

จาวาสคริปต์ (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

Linebreak และเยื้องในวงเพิ่ม แต่ไม่นับ หากคุณรู้สึกว่ามันคุณสามารถย้ายสิ่งนี้ไปยัง;บรรทัดที่แยกกันอีกครั้ง


ฮา! ฉันเพิ่งจะชี้ให้เห็นว่าคุณสามารถใช้greplในรหัส R ของคุณ ถ้าฉันแค่คิดว่าจะทำซ้ำรหัสผ่านการทดสอบสี่ครั้งเพื่อให้คุณสามารถตรวจสอบทั้งหมดในที่เดียว และคุณรู้ว่าถ้าเพียง แต่ผมคิดเกี่ยวกับและsample intToUtf8อย่างไรก็ตามคุณต้องเพิ่มreplace=TRUE(หรือมากกว่านั้นคุณต้องเพิ่ม,T) ในวิธีการตัวอย่างเพื่อให้แน่ใจว่าคุณได้รับรหัสผ่านที่เป็นไปได้ทั้งหมด
AmeliaBR

@AmeliaBR: ถูกต้องแก้ไขreplace=Tข้อผิดพลาดนั้นขอบคุณที่ชี้ให้เห็น การค้นหาintToUtf8ด้วยการคาดเดาชื่อที่น่าจะเป็นไปได้ด้วยการทำให้แท็บเสร็จสมบูรณ์ฉันใช้เวลาพอสมควร ฉันรู้ว่าต้องมีฟังก์ชั่นดังกล่าว แต่chrไม่ได้ใช้ชื่อทั่วไปที่ชอบและอื่น ๆ
MvG

@MvG: ฉันไม่เข้าใจว่าทำไมรหัส Python ของคุณถึงยุติเลย ทำไมคุณต้องว่า*4? ฉันคิดว่า regex ของคุณจะจับคู่กับสตริงใด ๆ โฆษณานั้นตัวอักษรตัวพิมพ์ใหญ่ตัวแรกตัวหนึ่งแล้วอะไรก็ตามจากนั้นตัวอักษรตัวเล็กตัวหนึ่งตัวใดตัวหนึ่งมากกว่าอะไร ... ฉันผิดอะไร
Martin Thoma

@moose: ตามที่คุณสังเกตเห็นแล้ว regex ของฉันจะตรวจสอบหมวดหมู่ที่จำเป็นในการสั่งซื้อเฉพาะ แต่โดยการต่อกันสี่สำเนาของผู้สมัครปัจจุบันฉันสามารถมั่นใจได้ว่าลำดับไม่สำคัญ: แม้ว่ารหัสผ่านของฉันคือสัญลักษณ์ตามด้วยตัวเลขตามด้วยตัวพิมพ์เล็กตามด้วยตัวพิมพ์ใหญ่แล้วก็จะมีการแข่งขัน วิธีเดียวที่การจับคู่อาจล้มเหลวคือถ้าหมวดหมู่หายไปโดยสิ้นเชิง โปรดทราบว่าฉันre.searchไม่ต้องการre.matchดังนั้น regex อาจจับคู่กับรหัสผ่านของผู้สมัครได้ทุกที่ สิ่งนี้อธิบายได้หรือไม่ว่าทำไมจึงยุติในที่สุด
MvG

อ่าผมไม่ได้สังเกตเห็นว่าคุณใช้แทนre.search re.matchนั่นอธิบายได้ *4แต่ผมก็ยังคิดว่าคุณไม่จำเป็นต้อง ขอบคุณสำหรับคำอธิบาย (+1)
Martin Thoma

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) จากบรรทัดคำสั่ง:

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

3
GeneratePasswordไม่รองรับสัญลักษณ์เต็มชุดที่ระบุในคำถาม ฉันไม่พบการรับประกันใด ๆ เกี่ยวกับจำนวนครั้งต่ำสุดของแต่ละประเภทอักขระ
MvG

2
คุณสามารถกระชับอีกโดยใช้และclass P string[] a
d3dave

@MvG นั่นน่าสนใจ ดูเหมือนว่าจะไม่รวมสัญลักษณ์ใด ๆ ที่ใช้กันทั่วไปในการเขียนอักขระที่เน้นเสียงในภาษาเช่นฝรั่งเศส อาจเป็นสมาร์ทย้าย การเปลี่ยนภาษาของคีย์บอร์ดจะเพียงพอที่จะใช้ในการตั้งรหัสผ่านของคุณ
Hand-E-Food

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

(เพิ่มช่องว่างเพื่อความชัดเจนเท่านั้น)

สร้างการเรียงสับเปลี่ยน 15 ตัวอักษรที่เป็นไปได้ทั้งหมดจาก 94 ตัวอักษร จากนั้นสุ่มเลือกหนึ่งรายการจนกว่าจะตรงกับเกณฑ์

เวทย์มนตร์อยู่ในการ q:qดำเนินการซึ่งสร้างชนิดข้อมูลปัจจัยใหม่ที่เป็นการโต้ตอบของปัจจัยทั้งหมดในqรายการแรกที่มีปัจจัยทั้งหมดในรายการที่สองด้วยการรวมกันที่เป็นไปได้ของรายการทั้งสองที่รวมอยู่ในรายการ " ระดับ "ของปัจจัยนั้น โต้ตอบ 15 สำเนาของรายการของอักขระที่อนุญาตและคุณจะได้รับ (94 ^ 15) ระดับที่เป็นไปได้

โปรดอย่าลองทำที่บ้าน รหัสใช้เวลาสองสามวินาทีในการคำนวณพีชคณิตสามตัวทั้งหมดฉันไม่สามารถจินตนาการได้ว่าจะต้องใช้เวลานานแค่ไหนในการคำนวณพีชคณิต 15 ตัวทั้งหมดถ้าคอมพิวเตอร์ของคุณไม่ได้ใช้หน่วยความจำไม่เพียงพอ ขณะ เมื่อฉันรันสคริปต์ (รหัสผ่านสามตัวอักษร) ที่เสร็จสิ้นเพื่อตรวจสอบรหัสผ่านแรกที่มันพ่นออกมาคือ "oO =" ซึ่งฉันคิดเกี่ยวกับผลรวมของปฏิกิริยาที่คุณควรมีต่อรหัสนี้


@MvG มีสคริปต์ R ที่มีประโยชน์มากกว่าและสั้นกว่ามากหากน้อยกว่านี้: codegolf.stackexchange.com/a/17700/12413
AmeliaBR

อย่างไรก็ตามฉันชอบความคิดของคุณ ตัวอย่างโค้ดกอล์ฟที่ฉันเห็นให้คุณสมบัติเฉพาะของภาษาทำงานหนัก และรหัสของคุณทำอย่างนั้นสำหรับ R ด้วยการโต้ตอบเหล่านั้น
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]

ตัวอย่าง

"<]} 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 น้อยลงโดยการลบช่องว่าง
Martin Thoma

@moose ฉันลบช่องว่างออกก่อนที่คุณจะแสดงความคิดเห็น :-) ฉันรู้สึกเหมือนjoinจะต้องมี: ผู้ใช้จะต้องเข้าใจไวยากรณ์รายการหลามจากผลลัพธ์: ['q', 'u', ...]หรือไม่
Jonathon Reinhart

1
ฉันคิดว่าจะลบการพิมพ์ออกเลย เมื่อขนาดเป็นไบต์สำคัญพวกเขาอาจอยู่ในเวลาของการ์ดเจาะ ด้วยวิธีนี้พวกเขาอาจจะสามารถอ่านหน่วยความจำ ... เพียงแค่มองมัน หรือพวกเขาเป็น "โปรแกรมเมอร์จริง": xkcd.com/378
Martin Thoma

1
หากฉันอ่านรหัสถูกต้องสิ่งนี้จะไม่เป็นไปตามข้อกำหนดด้านการเปลี่ยนลำดับทั้งหมดมันจะมีอักขระตัวพิมพ์เล็ก 12 ตัวเสมอทำให้รหัสผ่านที่มีกลุ่มอื่นมากกว่าหนึ่งกลุ่มaA$bc1111111111เป็นไปไม่ได้(เช่น)
IQAndreas

1
ในการป้องกันของ Johnathon ฉันคิดว่ากฎการเปลี่ยนลำดับจะถูกเพิ่ม 5 นาทีหลังจากโพสต์ของเขา
Hand-E-Food

4

Golfscript (60)

นับตั้งแต่ golfscript หายไปและเป็น noob ฉันต้องการฝึกต่อไป :)

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

มันเพิ่งสร้างอาร์เรย์ที่มีตัวละครสุ่ม 4 ตัวที่ต้อง + 11 และเรียงตามลำดับแบบสุ่ม


+1 {r}$สำหรับ นั่นเป็นวิธีที่ค่อนข้างสกปรกในการสลับรายการ - ฉันชอบ! ;-)
Ilmari Karonen

... อย่างไรก็ตามฉันไม่คิดว่ามันจะออกมาเช่น0Aa~~~~~~~~~~~~กัน :-(
Ilmari Karonen

3

จาวาสคริปต์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

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 of it ):

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

@ Hand-E-Food ฉันหมายถึงว่ามันไม่ได้สร้างไว้ใน JavaScript และเนื่องจากนักพัฒนาที่นี่ควรรู้วิธีสับเปลี่ยนอาร์เรย์ฉันรู้สึกว่าการใช้ฟังก์ชั่นในโค้ดนั้นไม่จำเป็น มันมีอยู่ในซอ - ปริศนา (บรรทัดที่ 16)
IQAndreas

1
จุดของฉันคือมันนับต่อการนับไบต์ของคุณ แต่ฉันเห็นว่าตอนนี้คุณได้ติดตั้งมันในเวอร์ชั่นกระชับแล้วดังนั้นโปรดอย่าสนใจฉัน :-)
Hand-E-Food

2

Clojure (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

เห็นมันใน Action - 2


1
ฉันมีปัญหาในการติดตามบรรทัดสุดท้าย แต่โค้ดดูเหมือนจะไม่ตรงตามข้อกำหนดด้านการเปลี่ยนลำดับทั้งหมด
IQAndreas

รหัสของคุณจะไม่สร้างรหัสผ่านใด ๆ ที่เริ่มต้นด้วย~0Aaหรือรหัสผ่านใด ๆ ที่จะตามมาด้วยb a
Heinzi

@Heinzi: ใช่ฉันเห็นด้วยกับการเปลี่ยนแปลงที่จำเป็นทั้งหมด r ไม่ได้คำนึงถึงมันแค่แสดงความยาว 15 ตัวเลือกแบบสุ่มจาก ... 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=

แสดงความคิดเห็น / เยื้อง:

%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

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

ฉันคิดว่า regex นี้อาจทำให้สั้นลงเล็กน้อย: ^.*(?=.{15,})(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!#$%&? "]).*$คุณสามารถจับคู่หนึ่งกับสิ่งนี้ได้ซึ่งจะจับคู่เมื่อมีหนึ่งตัวบน, ล่าง, หลัก, สัญลักษณ์
Vasili Syrakis

@ VasiliSyrakis ตกลงคุณอาจต้องเดินผ่านฉันไปสักหน่อย อย่าลังเลที่จะเริ่มห้องแชทถ้าคุณคิดว่ามันจะใช้เวลาสักครู่ สองสิ่งที่ฉันสับสน: 1. ) ฉันเห็นหมายเลข 15 รวมอยู่ที่นั่น นั่นคือเพื่อให้แน่ใจว่าสตริงมีความยาว 15 อักขระใช่หรือไม่ ถ้าเป็นเช่นนี้สามารถละเว้นตั้งแต่สคริปต์ที่เป็นธรรมชาติเพียงสร้างสตริง 15 ตัวอักษร 2. ) คุณหมายถึงอะไร "จะจับคู่ก็ต่อเมื่อมีหนึ่งตัวบน, ล่าง, หลัก, สัญลักษณ์"? หมายความว่ามันจะตรงกับเมื่อมีตรงหนึ่งของแต่ละหรืออย่างน้อยหนึ่งของแต่ละ? อดีตจะทำลายสิ่งต่าง ๆ
Iszi

RegEx ของคุณเพิกเฉยต่อการเรียงลำดับอักขระหรือไม่? ตัวอย่างเช่นถ้าปรับลงเพื่อให้ตรงกับสาย 4 ตัวละครทั้งสองจะ1aZ%และ(p3Rตรงกับ? ฉันมีปัญหาในการหาวิธีที่จะทำออนไลน์
Iszi

ทดสอบ 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

ฉันจะเปิดห้องแชทได้อย่างไร
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))))))

เขียนด้วยวิธีที่อ่านได้ง่ายขึ้น (และไม่สามารถเรียกใช้งานได้)

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

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

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

กึ่ง 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

ไม่รัดกุมเท่าคำตอบ 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

แน่นอนคุณถูกต้องฉันได้แก้ไขและบันทึกบางไบต์! ขอบคุณ!
Dom Hastings

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

เป็นจุดที่ดีผมคิดว่าผมเป็นกังวลว่า\Wเขาไม่ได้รวม_แต่คุณอย่างถูกต้องก็ไม่จำเป็น: gist.github.com/anonymous/8301237 ขอขอบคุณ!
Dom Hastings

1

Java 7 ( 270 234 ตัวอักษร)

สถานที่ตั้งเป็นเช่นเดียวกับที่ใช้โดย @assylias กับ java 8 (สร้างรหัสผ่านแบบสุ่มจนกระทั่งรหัสผ่านที่ถูกต้อง) อย่างไรก็ตามแทนที่จะใช้ lambdas รหัสผ่านจะถูกสร้างขึ้นโดยวนซ้ำ char และตรวจสอบความถูกต้องโดยจับคู่ 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);
  }
}

รหัสย่อ:

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


รุ่นไลเนอร์หนึ่งอัน (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
สิ่งนี้ไม่ครอบคลุมถึงการเรียงสับเปลี่ยนทั้งหมด เป็นตัวอย่างabcd1234ABCD{|}~จะไม่เกิดขึ้นเพราะ$symbolบังคับอย่างน้อยหนึ่งสัญลักษณ์ที่อยู่ระหว่าง ASCII 33 และ 47
Hand-E-Food

Dangit! คุณต้องชี้ให้เห็นความขี้เกียจของฉัน! เพิ่งล้อเล่น ... ฉันแก้ไขมันแล้ว ฉันยังสร้างอักขระ "ข้อกำหนด" แต่ละตัวไปที่ดัชนีแยกต่างหากภายในสตริงแทนที่จะรวมตัวกันสี่ตัวที่ดัชนีเดียวกัน ตอนนี้ถ้าเดียวที่ฉันจะลดระยะนี้ ...
ซิลี Syrakis

มีเหตุผลอะไรที่คุณไม่สามารถโกนหนวดตัวละครอีกสองสามตัวโดยการย่อ$SRให้สั้นลง$Q?
Iszi

นอกจากนี้คุณควรจะสามารถที่จะตัดสิ่งที่ชอบ(g(65..90))ลงไป65..90|g'. And change the งบ foreach` เพื่อforeach-objectลูปโดยใช้%นามแฝง ตัวอย่าง: foreach($N in (1..11)){... }ควรจะเป็นไปได้...1..11|%{ }ฉันค่อนข้างมั่นใจว่ามีการเพิ่มประสิทธิภาพอื่น ๆ ที่เป็นไปได้ แต่จริง ๆ แล้วฉันมีการใช้งานที่แตกต่างอย่างสิ้นเชิงในใจว่าฉันวางแผนที่จะลองในภายหลัง
Iszi

คำแนะนำที่ดี :) ฉันย่อให้เหลือ 213 bytes ถ้าฉันนำ carriage return และแทนที่ด้วย semicolons
Vasili Syrakis

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

ฉันอาจตีความผิด regex แต่ฉันคิดว่าสิ่งที่ชอบ~{}|1234abcdABCDจะล้มเหลว regex
Hand-E-Food

1
จะไม่ทำงาน:"~{}|1234abcdABCD" 60 cycle "[A-Z].*[a-z].*[0-9].*[\\W_]" findall empty? not => t
Björn Lindqvist

ฉันจะเอาคำของคุณไป :-)
Hand-E-Food

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

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

สตริงที่พิมพ์มีเครื่องหมายคำพูดล้อมรอบและหนีอักขระเครื่องหมายทับขวาและเครื่องหมายคำพูด; หากไม่สามารถยอมรับได้printสามารถแทนที่ได้putStrLnอีก 3 ไบต์ นี่คือรุ่นที่อ่านได้มากขึ้น:

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

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

สร้างอักขระ ASCII 15 ตัวเพื่อสุ่มชุดที่เป็นไปได้ทั้งหมด จากนั้นใช้รูปแบบการแสดงออกปกติเพื่อตรวจสอบว่ามีอย่างน้อยหนึ่งในแต่ละเกณฑ์

หากไม่เป็นเช่นนั้นรหัสผ่านจะปรากฏขึ้นหากไม่มี "การทำซ้ำ" จะปรากฏขึ้น

มอบเครดิตให้กับ Bart Kiers สำหรับรูปแบบการแสดงผลปกติ: https://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char-th/ บน


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] นำเข้าแบบสุ่ม ตัวเลขในรายการที่คูณด้วยสามจะเป็นเส้นขอบระหว่างช่วงในตาราง 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
msgstr "จะต้องสามารถสร้างการเรียงสับเปลี่ยนทั้งหมดของอักขระที่อนุญาตทั้งหมด". ฉันไม่คิดว่าจะเป็นเช่นนั้นเนื่องจากมีการใช้ช่วงในลำดับเดียวกันเสมอ ... ?
Joachim Isaksson

คุณพูดถูกขอบคุณ อันที่จริงฉันไม่ได้สังเกตว่าควรใช้ช่วงแบบสุ่มพวกเขาควรจะสับผมจะแก้ไขในช่วงเวลาหนึ่ง
Pawelmhm

สิ่งนี้จำเป็นต้องรวมimport randomไว้ในรหัส
Mego

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

หรือหนึ่งบรรทัด (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.