Генератор випадкових паролів


40

Сервер домену вимагає, щоб усі співробітники мали надійний, випадковий пароль, що відповідає наступним правилам:

  • Рівно 15 символів.
  • Тільки символи для клавіатури (як показано в типі коду нижче). Навчання продажів використовувати коди ALT + NUMPAD не дозволяється.
  • Принаймні 1 малі літери: abcdefghijklmnopqrstuvwxyz
  • Принаймні 1 верхній регістр: ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • Принаймні 1 цифрова цифра: 0123456789
  • Щонайменше 1 символ: `~!@#$%^&*()_+-={}|[]\:";'<>?,./

Для цього ІТ замовили і розповсюдять Генератор випадкових паролів для всіх співробітників. Усі співробітники повинні будуть використовувати Генератор випадкових паролів. Вимоги до Генератора випадкових паролів, крім обмежень щодо пароля, наведені вище:

  • Він повинен бути здатний генерувати всі перестановки всіх допустимих символів.
  • Він повинен відображати створений пароль на екрані.
  • Код повинен бути якомога меншим (у байтах).

Надішліть запропоноване рішення протягом наступного тижня.


10
Ви також повинні вимагати, щоб усі дозволені паролі відображалися з однаковою ймовірністю (інакше я просто можу скласти список із 30 символів із дозволеними символами, перетасувати його та надати перші 15 з них)
Мартін Тома

@moose, погодився. Я додав нове правило.
Hand-E-Food

22
ІТ-хлопці повинні бути звільнені або принаймні краще освічені: якщо ви генеруєте паролі випадковим чином, обмеження набору допустимих паролів тими, що містять принаймні один символ кожної категорії, фактично послаблює паролі, оскільки це зменшує розмір допустимий набір. І наші програми були б набагато простішими, якби нам не довелося перевіряти на це… Гаразд, не змінюйте конкурс після надходження стільки заявок; це добре, як виклик.
MvG


1
Ви справді не відповідали на @moose, вимагаючи, щоб усі паролі були генеративними. Вони повинні з’являтися з однаковою ймовірністю.
Етан Болкер

Відповіді:


29

Математика (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 має функцію для всього, але це ?
Конрад Боровський

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замість pцього, тому що pдрукує рядок, укладений у "лапки", а деякі символи втекли із зворотним нахилом.

Рубін, 70 байт

Як зазначає Вентеро, ~його можна пропустити перед регулярними виразами і printможе замінити puts$_. Але з некрасивим висновком це може призвести до того, що ви також можете надрукувати всі відхилені паролі, видавивши їх в однолінійку:

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

Пояснення

Як вимагалось. $_є напів-магічна змінна , яка містить останній рядок від входу - так що ви не завжди потрібно зберігати його, як це . Однак ми використовуємо його через іншу властивість, а саме те, що ~оператор застосовує до нього регулярний вираз, трюк, який я вперше дізнався chron . Я замінив використання all, але це має бути досить легко зрозуміти, якщо ви отримаєте решту ( див. Документи ).


2
Не могли б ви трохи пояснити свій код? Що робить .all?{|r|~r}? Що робить $_=?
Мартін Тома

3
Зразок рядка розумний і все, але я думаю, що це порушує "Він повинен бути здатний генерувати всі перестановки усіх допустимих символів". Ніде не сказано, що пароль може містити рекламу лише щодо листів. Якщо z - дозволений символ, має бути шанс> 0, що z знаходиться у паролі.
nitro2k01

1
Чи \Wвключає в Ruby підкреслення _? У більшості діалектних регексів я знаю, що це не так. І якщо ваш код не міг генерувати паролі, коли єдиний _був не буквено-цифровим символом, то це порушило б одну вимогу. Другий підхід дуже очевидно порушує цю вимогу, але, мабуть, він тоді не був правильно сформульований.
MvG

1
@MvG: Ти маєш рацію. \Wне містить підкреслення в сумісному PerE RegEx ( джерело ).
Мартін Тома

1
Крім того, на ваше рішення впливає та сама проблема @moose, і у мене був з Python: sampleне повторює елементи, тому паролі з повторними елементами не можуть бути сформовані вашим кодом. Чи можете ви виправити ці два питання, щоб відповідь відповідала на запитання? Побачивши, як ваше провідне рішення, за винятком Wolfram Alpha, було б непогано побачити, чи можете ви відповідати та все-таки зберігати лідерство. Я думаю, це не повинно бути занадто важким.
MvG

12

Java 8 - 354 329 319 275 267 символів

Для задоволення, використовуючи лямбдаси з 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++? Або використовувати бітові маски, тобто речі як a|=1наскрізь a|=8, з a<15умовою циклу. Це економить ще 13 символів, якщо я правильно порахував.
MvG

@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)
  • Дякую MvG, який мені сказав, що цього немає \uі \lне існує в регексе Python.
  • Завдяки grc, який сказав мені, що random.sampleбез заміни, будьте всі можливі дозволені паролі, нам потрібен вибірки із заміною.

Використання вади в описі проблеми

В даний час опис проблеми не вимагає, щоб кожен символ / цифра відображався з однаковою ймовірністю. За допомогою наступного рішення ви не можете робити жодних припущень щодо одного символу та / або позиції. Але ви можете це зробити з декількома.

Python 2.X + 3.X (62 символи)

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

Завдяки daniero за ідею використовувати зразок.


Дуже гладко знаходить недолік! Я підключив цю, але бонусну бали за її ідентифікацію. :-)
Hand-E-Food

Твій рід і перевірка схожий на мій підхід. З цікавості: де це \lі так далі для регексів пітона? Не бачити цього в посиланні . Мій Python 3.3.3 навіть не прийме "\u". str(…)Чи не приєднується букви в будь-якому 3.3.3 або 2.7.6. Одне з пропозицій для optmization: all(s("\\"+i,p)for i in "dluW").
MvG

random.sampleвибирає елементи без заміни, тому не всі паролі можливі.
grc

@MvG: Дякую Я щойно це бачив \uі \lє лише vim.
Мартін Тома

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=і розбиття рядка спереду, це ще три символи, але це дозволяє вам запускати річ кілька разів. Ви, очевидно, також можете замінити всі нові рядки на ;так, щоб у вас був однолінійний лайнер, який ви можете виконувати так часто, як вам захочеться.

Крім того, вам слід було б встановити LC_ALL=Cчи не встановити будь-які змінні для конкретного локального середовища ( LANGі LC_CTYPEзокрема), оскільки діапазони символів залежать від порядку порівняння, рівного порядку ascii.

/dev/urandomє джерелом випадкових байтів. !-~- це діапазон усіх допустимих символів, визначений у запитанні. tr -dcвидаляє всі символи, не вказані в наступному аргументі. headзаймає 15 з інших символів. grepперевіряє, чи виникає кожен із необхідних видів хоча б один раз. Його вхід складається з чотирьох копій кандидата, тому порядок символів не має значення, тому всі можливі паролі мають шанс вибрати. Значок " -qgrep" пригнічує вихід.

З невідомих причин /dev/randomзамість /dev/urandomвіків. Схоже, що ентропія досить швидко вичерпалася. Якщо ви cdввійдете /dev, ви можете уникнути ще кількох байтів, але це трохи схоже на обман.

Пітон 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 копій списку допустимих листів. Таким чином, кожна комбінація все-таки може відбуватися, хоча ті, що повторюються, бувають рідше. Але я вирішую вважати це особливістю, а не помилкою, оскільки питання не вимагало однакової ймовірності для всіх перестановок, лише можливість.

Пітон 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.

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-код. Якби я думав повторити тестовий пароль чотири рази, щоб ви могли зробити всі перевірки в одному. І ви знаєте, якби тільки я думав sampleі про intToUtf8. Однак вам потрібно додати replace=TRUE(або більш коротко, вам просто потрібно додати ,T) до вашого зразкового методу, щоб переконатися, що ви отримуєте всі можливі паролі.
AmeliaBR

@AmeliaBR: Ви праві, виправте цю replace=Tпомилку, дякую , що вказали на це. Пошук intToUtf8, відгадуючи ймовірні імена із заповненням вкладки, зайняв у мене досить багато часу; Я знав, що така функція повинна існувати, але більш поширені назви на зразок chrтощо не використовувались.
MvG

@MvG: Я не розумію, чому ваш код Python взагалі припиняється. Навіщо вам це потрібно *4? Я думав, що ваш регулярний вираз буде відповідати будь-якому рядку, це оголошення спочатку одна велика літера, потім що-небудь, потім одна маленька літера, ніж усе, що я помилився?
Мартін Тома

@moose: Як ви вже помітили, мій регулярний вимір перевіряє необхідні категорії в певному порядку. Але, зробивши конкатенацію чотирьох копій поточного кандидата, я можу переконатися, що наказ більше не має значення: Навіть якщо мій пароль - це символи, за якими значать цифри, а за ними - малі регістри, а потім великі регістри, то все одно буде збіг. Єдиний спосіб, коли збіг може бути невдалим - це якщо категорія взагалі відсутня. Також зауважте, що я цього re.searchне роблю re.match, тому регулярний вираз може відповідати будь-де в паролі кандидата. Чи пояснює це, чому воно врешті-решт припиниться?
MvG

Ах, я не помітив, що ви використовуєте re.searchзамість цього re.match. Це пояснює це. Але я все ще думаю, що вам це не потрібно *4. Дякую за пояснення (+1)
Мартін Тома

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

Пітон 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 менше, видаляючи пробіли.
Мартін Тома

@moose Я вийняв пробіли перед тим, як ви прокоментували :-) Я відчуваю, що joinщось там має бути: Чи очікують, що користувачі зрозуміють синтаксис списку python з виводу ['q', 'u', ...]:?
Джонатан Райнхарт

1
Я взагалі думав про видалення друку. Коли розмір у байтах важливий, вони можуть жити в часі перфокарт. Таким чином, вони зможуть прочитати пам'ять ... просто подивившись на неї. Або вони "справжні програмісти": xkcd.com/378
Мартін Тома

1
Якщо я читаю код правильно, він не відповідає всім вимогам перестановок , він завжди матиме 12 малих символів, що робить паролі з більш ніж однією з інших груп (наприклад aA$bc1111111111) неможливими.
IQAndreas

1
На захист Джоннатана, я думаю, що правило перестановок було додано через 5 хвилин після його поста.
Hand-E-Food

4

Гольфскрипт (60)

Оскільки обл. гольфскрипт відсутній, і як noob мені потрібна практика все одно :)

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

Він просто створює масив з 4 необхідних + 11 випадкових символів і сортує у випадковому порядку.


+1 для {r}$. Це досить брудний спосіб перетасувати список - мені це подобається! ;-)
Ільмарі Каронен

... однак, я не думаю, що це може вийти, наприклад 0Aa~~~~~~~~~~~~. :-(
Ілмарі Каронен

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

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, і оскільки будь-які розробники тут повинні знати, як перетасувати масив, я відчував, що функція в коді була непотрібною. Він доступний в JS-Fiddle, хоча (рядок 16).
IQAndreas

1
Моя думка, вона рахується з вашим числом байтів. Але я бачу, що ви реалізували це в ущільненій версії, тому, будь ласка, ігноруйте мене. :-)
Hand-E-Food

2

Clojure (63):

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

Але їх потрібно вдосконалити, щоб переконатися, що містить щонайменше по 1 символу кожної категорії (верхній, нижній, цифр, символ).


2

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

Побачити це в дії - 1

дивіться це в Дії - 2


1
У мене виникають проблеми з дотриманням останнього рядка, але, схоже, код не відповідає всім вимогам перестановок .
IQAndreas

Ваш код ніколи не генерує жодного пароля, починаючи з цього ~0Aa, і будь-якого пароля, за яким bслід a.
Хайнзі

@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

Код Гофледа

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)(?=.*[!#$%&? "]).*$ви можете виконати один збіг з цим, який буде відповідати лише тоді, коли є один верхній, нижній, цифрний, символьний.
Василь Сіракіс

@VasiliSyrakis Добре, можливо, вам доведеться трохи пройти через мене. Не соромтеся заводити кімнату чату, якщо ви думаєте, що це займе деякий час. Пару речей, в яких я плутаюсь: 1.) Я бачу, що число 15 включено туди. Це, щоб переконатися, що в рядку рівно 15 символів? Якщо це так, це можна опустити, оскільки сценарій, природно, генерує лише 15-символьні рядки. 2.) Що ви маєте на увазі "відповідатиме лише тоді, коли є один верхній, нижній, цифрний, символьний"? Чи означає це , що буде відповідати тільки тоді , коли є рівно один з кожного, або принаймні один з кожного? Колишній зламає речі.
Іссі

Також ваш RegEx ігнорує впорядкування символів? Наприклад, якщо налаштований вниз , щоб відповідати рядки 4-символів, буде як 1aZ%і (p3Rматч? У мене були деякі труднощі в пошуку способів зробити це в Інтернеті.
Іссі

Тестував новий 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
Іссі

Як відкрити кімнату чату?
Василь Сіракіс

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).)
Ільмарі Каронен

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

Напівгольф;

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

Перл, 92

Не настільки стислий, як відповідь Рубі, але я впевнений, що майстер 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

Дійсно, ви маєте рацію, я це виправив і зберег кілька байтів! Дякую!
Дом Гастінгс

1
Ви впевнені в цьому [[:punct:]]? Я думаю, що я віддаю перевагу , which is shorter and of which I'm even more sure that it is correct, at least combined with your діапазону '[\ W_] 33..127'.
MvG

Хороший момент, я думаю, що я був стурбований тим, що \Wвін не включав _, але ви абсолютно праві, це не потрібно: gist.github.com/anonymous/8301237 . Дякую!
Дом Гастінгс

1

Java 7 ( 270 234 символів)

Приміщення те саме, що використовується @assylias з java 8 (генеруйте випадкові паролі до дійсного пароля). Однак, замість використання лямбда, пароль генерується за допомогою ітерації масиву знаків і перевіряється шляхом відповідності регулярному вираженню.

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
}

Подяку Ізі за різні поради щодо скорочення коду.


1
Це не охоплює всіх перестановок. Як приклад, abcd1234ABCD{|}~ніколи не вийде, оскільки $symbolзмушує принаймні один із символів бути між ASCII 33 та 47.
Hand-E-Food

Dangit! Треба вказати на мою лінь !? Жартую ... Я зараз це відредагував. Я також змусив кожен символ "вимоги" перейти до окремого індексу в рядку, а не згрупувати чотири разом в один і той же індекс. Тепер якби я міг би це скоротити ...
Василь Сиракіс

Чи є якась причина, що ви не можете поголити ще пару символів, скоротивши $SRїх, можливо $Q?
Іссі

Ви також повинні мати можливість вирізати такі речі, як, наприклад (g(65..90)), для 65..90|g'. And change the випередження 'висловлювань до foreach-objectциклів, використовуючи %псевдонім. Приклад: foreach($N in (1..11)){... }має бути здійснимо , як 1..11|%{... }. Я впевнений, що можливі й інші оптимізації, але я маю на увазі зовсім іншу реалізацію, яку я планую спробувати пізніше.
Іссі

Приємні поради :) Я скоротив її до 213 байт, якщо вийму повернення каретки і замінюю крапками з комою.
Василь Сіракіс

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

1
Ні, це не спрацює:"~{}|1234abcdABCD" 60 cycle "[A-Z].*[a-z].*[0-9].*[\\W_]" findall empty? not => t
Бьорн Ліндквіст

Я візьму за це ваше слово. :-)
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

Хаскелл, 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

Випадково генерується 15 символів ASCII, тому можливі всі можливі комбінації. Потім використовує шаблон регулярного вираження, щоб перевірити, чи містить він принаймні один із кожного критерію.

Якщо це так, відображається пароль, якщо не відображається "повторно".

Кредит Барту Кірсу за шаблон регулярного вираження: 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

Пітон (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 "Він повинен бути здатний генерувати всі перестановки усіх допустимих символів." Я не думаю, що це робить так, оскільки діапазони завжди застосовуються в одному порядку ...?
Йоахім Ісакссон

Ви маєте рацію, дякую. Справді, я не помічав, що діапазони слід застосовувати у випадковому порядку, їх слід переміщувати, я це відредагую за мить.
Pawelmhm

Це потрібно фактично включати 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)));

Або в одному рядку (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)));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.