регулярное выражение для парольной фразы

Я новичок в регулярном выражении и пытаюсь создать регулярное выражение для проверки парольных фраз. Я хотел бы подтвердить, что парольная фраза имеет:

  • n количество слов или более
  • слова должны быть разделены пробелами
  • слова, каждое из n символов или более
  • число хотя бы в одном из слов
  • хотя бы один специальный символ в одном из слов

Это то, что у меня есть до сих пор

^(?=.*?((?:.*?\b[a-zA-Z0-9]{2,40}\b)\s*){3,})(?=.*?[@#$%^&+=])(?=.*?[0-9]).*$

Он соответствует этой Pe2sI#sHy?ThYulU# фразе, в которой нет по крайней мере 3 слов (без пробелов). Что я делаю неправильно?


person jmm312    schedule 25.04.2012    source источник
comment
Я бы заменил ваше последнее требование минимальной длиной. Одним из преимуществ кодовых фраз является то, что они избавляют от необходимости запоминать кучу сумасшедших цифр и специальных символов, но при этом сохраняют высокий уровень вариативности, поскольку они очень длинные.   -  person Justin Morgan    schedule 26.04.2012
comment
Это правда, но отсутствие специальных символов делает парольную фразу уязвимой для атак с использованием статистического анализа использования слов, особенно потому, что люди склонны использовать ограниченный набор слов. Добавление хотя бы одного специального символа улучшает энтропию.   -  person jmm312    schedule 30.04.2012


Ответы (2)


Вы должны использовать \s+ вместо \s*. Последний допускает ноль пробелов, первый требует по крайней мере один. Но ваше регулярное выражение слишком сложное. Попробуй это:

^                 # Start of string
(?=.*\d)          # Assert at least one digit
(?=.*[@#$%^&+=])  # Assert at least one special char
\s*               # Optional leading whitespace
(?:               # Match...
 \S{2,}           #  at least 2 non-spaces
 \s+              #  at least 1 whitespace
){2,}             # at least 2 times
\S{2,}            # Match at least 2 non-spaces (making 3 "words" minimum)
person Tim Pietzcker    schedule 25.04.2012
comment
+1, потому что я строил аналогичный. Вместо этого я бы использовал [[:punct:]] для специального символа. - person Birei; 26.04.2012
comment
Похоже, это не работает, с \s+ фраза testing# 123 позволяет тесту не пройти проверку, пока я не передвину # в последнее слово. Мне нужен хотя бы один специальный символ в любом слове. Спасибо за вашу помощь. - person jmm312; 26.04.2012
comment
извините, ответил be4, я видел ваши правки с предложенным регулярным выражением. Я проверю это сейчас. Спасибо! - person jmm312; 26.04.2012

Немного поздно, так что это просто наблюдение.

Это отсылка к методу @Tim Pietzcker.
Хотя "слова" могут быть любыми, если вы хотите потребовать, чтобы по крайней мере
3 слова имели [a-zA-Z0-9]{2,40} встроенные символы, вы можете сделать это.

^                      # String start
(?=.*[@#$%^&+=])       # Assert 1 special char
(?=.*\d)               # Assert 1 digit
(?:                    # Special 'Word Group'  -- Need 2 words
   .*                     # Any char, 0 or more times
   [a-zA-Z0-9]{2,40}      # Alpha/num char, 2 to 40 times
   .*                     # Any char, 0 or more times
   \s                     # a whitespace, only 1 required
){2}                   # 'Word Group' end, do 2 times
.*                     # Any char, 0 or more times
[a-zA-Z0-9]{2,40}      # Alpha/num char, 2 to 40 times -- Need 1 word

Это должно соответствовать как минимум 3 специальным словам [a-zA-Z0-9]{2,40}, разделенным как минимум 1 пробелом
, включая цифру и специальный символ.

обновить

Да, вы можете объединить это в одну группу, проделывая это {3} раза двумя известными мне способами.

Использовать буфер захвата в качестве флага

^(?=.*[@#$%^&+=])(?=.*\d)(?:(?:(?!\1)|\s).*[a-zA-Z0-9]{2,40}().*){3} 
                                                       ^          ^
---------------------------------------   

^                      # String start
(?=.*[@#$%^&+=])       # Assert 1 special char
(?=.*\d)               # Assert 1 digit
(?:                    # Special 'Word Group'
   (?:                    #.. grping start ....
        (?!\1)              # Either capt group 1 is UN-DEFINED
      | \s                  # OR, require a whitespace
    )                     #.. grping end ....
   .*                     # Any char, 0 or more times
   [a-zA-Z0-9]{2,40}      # Alpha/num char, 2 to 40 times
   ()                     # DEFINE Capture group 1
   .*                     # Any char, 0 or more times
){3}                   # 'Word Group' end, do 3 times

Или, используя условное

^(?=.*[@#$%^&+=])(?=.*\d)(?:(?(1)\s).*([a-zA-Z0-9]{2,40}).*){3}
                                                   ^         ^
---------------------------------------   

^                      # String start
(?=.*[@#$%^&+=])       # Assert 1 special char
(?=.*\d)               # Assert 1 digit
(?:                    # Special 'Word Group'
   (?(1)\s)               # Conditional, require a whitespace if capture group 1 captured anything
   .*                     # Any char, 0 or more times
   ([a-zA-Z0-9]{2,40})    # Capture group 1, Alpha/num char, 2 to 40 times
   .*                     # Any char, 0 or more times
){3}                   # 'Word Group' end, do 3 times
person Community    schedule 25.04.2012
comment
Спасибо! Ваш ответ соответствует дополнительному требованию ограничения длины слова. Есть ли другой способ выразить это, чтобы, если есть необходимость изменить требования к длине слова и количеству слов, вам нужно было изменить только 2 места или меньше, как в исходном выражении. Я спрашиваю это ради удобочитаемости и избегания ошибок любым, кто читает мой код. Ваша помощь приветствуется. - person jmm312; 30.04.2012
comment
@ jimm312 - Конечно, это не должно быть слишком сложно. Проверьте обновление. Ваше здоровье! - person ; 01.05.2012