암호 강도를 확인하는 정규식


142

내 비밀번호 강도 기준은 다음과 같습니다.

  • 8 자 길이
  • 대문자 2 자
  • 1 특성 (!@#$&*)
  • 2 자리 (0-9)
  • 소문자 3 자

누군가 나에게 같은 정규식을 줄 수 있습니까? 모든 조건은 비밀번호로 충족해야합니다.


2
암호 보안 수단을 인터넷에 크게 신뢰 하시겠습니까?
Borealid

12
@Borealid : 비밀번호 정책을 게시하면 일반적으로 보안에 큰 영향을 미치지 않습니다 . 만약 그렇다면, 당신의 정책은 나쁜 ( "만 password하고 hello123유효한 암호입니다!").
Joachim Sauer

3
@Joachim Sauer : 그게 내가 의도 한 바가 아닙니다. 내가 의미하는 바는 포스터가 아마 그가받는 정규식을 믿을 것이라고 생각했다. 그런 좋은 생각이 아닙니다.
Borealid

3
사실이 정규식은 내가 :)을 신뢰하지 맹목적으로 사랑하는 케이스를 테스트합니다 서비스 코드가 될 것입니다
아제 Kelkar

9
복잡한 비밀번호 규칙은 일반적으로 더 안전한 비밀번호로 이어지지 않으며, 중요한 길이는 최소 길이입니다. 사람들은 수많은 강력한 암호를 기억할 수 없으며 이러한 규칙은 올바른 암호 체계를 방해 할 수 있습니다. 예를 들어 "Password-2014"와 같은 취약한 암호를 사용하면 이러한 규칙을 무시할 수 있습니다. 종종 더 강한 암호 대신 더 약한 암호로 끝납니다.
martinstoeckli

답변:


427

긍정적 인 미리보기 어설 션을 사용하여 이러한 검사를 수행 할 수 있습니다.

^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$

루블 링크

설명:

^                         Start anchor
(?=.*[A-Z].*[A-Z])        Ensure string has two uppercase letters.
(?=.*[!@#$&*])            Ensure string has one special case letter.
(?=.*[0-9].*[0-9])        Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8}                      Ensure string is of length 8.
$                         End anchor.

92
적어도 길이를 원하는 사람은 다음 과 같이 n바꾸십시오 .{8}..{n,}
NullUserException

14
자세한 설명을 보려면 +1 내 비밀번호 규칙은 다르지만 귀하의 답변에 따라 정규식을 조정할 수 있습니다.
Morvael

14
정규식에서 일어나는 일을 설명해 주셔서 감사합니다. 이것은 실제로 구문을 사용해 본 적이없는 사람들에게 훌륭한 학습 예입니다.

4
나는 또한 정규 표현식에 대한 설명에 감사드립니다. 여러 번, 나는 실제로 무슨 일이 일어나고 있는지 이해하지 않고 내가 찾은 복잡한 정규 표현식을 사용합니다.
Nicholas Smith

4
훌륭한 패턴, 왜 수량 화기를 사용하지 않는지 궁금합니다. 최소 1 개의 특수 문자, 1 개의 숫자, 1 개의 특수 문자, 8 자 : ^ (? =. * ([AZ]) {1,}) (? =. * [! @ # $ & *] {1,}) ( ? =. * [0-9] {1,}) (? =. * [az] {1,}). {8,100} $
RockOnGom 2016 년

11

길이가 0 인 긍정적 인 예측을 사용하여 각 구속 조건을 개별적으로 지정할 수 있습니다.

(?=.{8,})(?=.*\p{Lu}.*\p{Lu})(?=.*[!@#$&*])(?=.*[0-9])(?=.*\p{Ll}.*\p{Ll})

지원하지 않는 정규식 엔진의 경우 \p표기하고 순수한 ASCII가 충분하다, 당신은 대체 할 수 \p{Lu}[A-Z]\p{Ll}함께 [a-z].


8

위의 답변은 완벽하지만 큰 정규 표현식 대신 여러 개의 작은 정규 표현식을 사용하는 것이 좋습니다 .
긴 정규 표현식을 분할하면 몇 가지 장점이 있습니다.

  • 읽고 쓰기 쉬움
  • 디버그하기 쉬움
  • 정규식의 일부를 추가 / 제거하기 쉬움

일반적으로이 접근 방식은 코드를 쉽게 유지 관리 할 수 ​​있도록 유지 합니다.

나는 Swift 에서 작성한 코드를 예로 들어 설명합니다.

struct RegExp {

    /**
     Check password complexity

     - parameter password:         password to test
     - parameter length:           password min length
     - parameter patternsToEscape: patterns that password must not contains
     - parameter caseSensitivty:   specify if password must conforms case sensitivity or not
     - parameter numericDigits:    specify if password must conforms contains numeric digits or not

     - returns: boolean that describes if password is valid or not
     */
    static func checkPasswordComplexity(password password: String, length: Int, patternsToEscape: [String], caseSensitivty: Bool, numericDigits: Bool) -> Bool {
        if (password.length < length) {
            return false
        }
        if caseSensitivty {
            let hasUpperCase = RegExp.matchesForRegexInText("[A-Z]", text: password).count > 0
            if !hasUpperCase {
                return false
            }
            let hasLowerCase = RegExp.matchesForRegexInText("[a-z]", text: password).count > 0
            if !hasLowerCase {
                return false
            }
        }
        if numericDigits {
            let hasNumbers = RegExp.matchesForRegexInText("\\d", text: password).count > 0
            if !hasNumbers {
                return false
            }
        }
        if patternsToEscape.count > 0 {
            let passwordLowerCase = password.lowercaseString
            for pattern in patternsToEscape {
                let hasMatchesWithPattern = RegExp.matchesForRegexInText(pattern, text: passwordLowerCase).count > 0
                if hasMatchesWithPattern {
                    return false
                }
            }
        }
        return true
    }

    static func matchesForRegexInText(regex: String, text: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = text as NSString
            let results = regex.matchesInString(text,
                options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substringWithRange($0.range)}
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
}

또한 위와 같이 복잡한 정규 표현식을 사용하면 치명적인 역 추적에 쉽게 노출 될 수 있습니다 ( regular-expressions.info/catastrophic.html ). 사용자가 "이상한"암호를 사용했기 때문에 하루 동안 서버가 100 % CPU로 정지 할 때까지이 사실을 알 수 없습니다. 예 : ^ ([a-z0-9] +) {8,} $ (오류가
보이

5

나는 추가하는 것이 좋습니다

(?!.*pass|.*word|.*1234|.*qwer|.*asdf) exclude common passwords

1

codaddict의 솔루션은 정상적으로 작동하지만 조금 더 효율적입니다. (Python 구문)

password = re.compile(r"""(?#!py password Rev:20160831_2100)
    # Validate password: 2 upper, 1 special, 2 digit, 1 lower, 8 chars.
    ^                        # Anchor to start of string.
    (?=(?:[^A-Z]*[A-Z]){2})  # At least two uppercase.
    (?=[^!@#$&*]*[!@#$&*])   # At least one "special".
    (?=(?:[^0-9]*[0-9]){2})  # At least two digit.
    .{8,}                    # Password length is 8 or more.
    $                        # Anchor to end of string.
    """, re.VERBOSE)

부정 된 문자 클래스는 한 번의 단계로 원하는 문자까지 모든 것을 소비하므로 역 추적이 필요 없습니다. 도트 스타 솔루션은 잘 작동하지만 역 추적이 약간 필요합니다. 물론 암호와 같은 짧은 대상 문자열을 사용하면 이러한 효율성 향상은 무시할 수 있습니다.


정확한지 확인해 주시겠습니까? 트리플 큰 따옴표와 물음표 사이의 첫 번째 줄에 둥근 괄호가 있기 때문에 의심 스럽습니다. 파이썬 주석 (해시)이 나중에 있음을 알 수 있습니다. 엔드 앵커 (달러 기호) 근처에 해당 닫는 둥근 브래킷을 볼 수 없습니다. 나는 정규 표현식이 아니라고 언급해야합니다.
lospejos

@lospejos-#은 일반적인 한 줄 주석의 시작이 아닙니다. 이 해시는 a 로 시작하고 a 로 끝나는 주석 그룹의 일부입니다 . 이 정규식에는 불균형이 없습니다. (?#)
ridgerunner 2016 년

1
import re

RegexLength=re.compile(r'^\S{8,}$')
RegexDigit=re.compile(r'\d')
RegexLower=re.compile(r'[a-z]')
RegexUpper=re.compile(r'[A-Z]')


def IsStrongPW(password):
    if RegexLength.search(password) == None or RegexDigit.search(password) == None or RegexUpper.search(password) == None or RegexLower.search(password) == None:
        return False
    else:
        return True

while True:
    userpw=input("please input your passord to check: \n")
    if userpw == "exit":
        break
    else:
        print(IsStrongPW(userpw))

1

@codaddict의 솔루션이 작동합니다.

또한 일부 규칙을 다음과 같이 변경하는 것을 고려해야합니다.

  1. %, ^, (,),-, _, + 및 마침표와 같은 특수 문자를 추가하십시오. 미국 키보드의 숫자 기호 위에 놓친 모든 특수 문자를 추가하고 있습니다. 정규식이 사용하는 것을 피하십시오.
  2. 비밀번호를 8 자 이상으로 설정하십시오. 정적 숫자뿐만 아니라 8.

위의 개선과 더 많은 유연성과 가독성을 위해 정규 표현식을 수정했습니다.

^(?=.*[a-z]){3,}(?=.*[A-Z]){2,}(?=.*[0-9]){2,}(?=.*[!@#$%^&*()--__+.]){1,}.{8,}$

기본 설명

(?=.*RULE){MIN_OCCURANCES,}     Each rule block is shown by (){}. The rule and number of occurrences can then be easily specified and tested separately, before getting combined

상해

^                             start anchor
(?=.*[a-z]){3,}               lowercase letters. {3,} indicates that you want 3 of this group
(?=.*[A-Z]){2,}               uppercase letters. {2,} indicates that you want 2 of this group
(?=.*[0-9]){2,}               numbers. {2,} indicates that you want 2 of this group
(?=.*[!@#$%^&*()--__+.]){1,}   all the special characters in the [] fields. The ones used by regex are escaped by using the \ or the character itself. {1,} is redundant, but good practice, in case you change that to more than 1 in the future. Also keeps all the groups consistent
{8,}                          indicates that you want 8 or more
$                             end anchor

마지막으로 테스트 목적으로 위의 정규 표현식을 사용한 robulink 가 있습니다.


감사합니다 @AFract. 내 코드에서 사용하고 있습니다. 가독성과
반복성을 좋아

0

PHP의 경우 이것은 잘 작동합니다!

 if(preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 
 'CaSu4Li8')){
    return true;
 }else{
    return fasle;
 }

이 경우 결과는 사실입니다

@ridgerunner에 대한 감사


왜 안돼 return preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 'CaSu4Li8')?
codidact.com로 이동 aloisdg

0

다른 해결책 :

import re

passwordRegex = re.compile(r'''(
    ^(?=.*[A-Z].*[A-Z])                # at least two capital letters
    (?=.*[!@#$&*])                     # at least one of these special c-er
    (?=.*[0-9].*[0-9])                 # at least two numeric digits
    (?=.*[a-z].*[a-z].*[a-z])          # at least three lower case letters
    .{8,}                              # at least 8 total digits
    $
    )''', re.VERBOSE)

def userInputPasswordCheck():
    print('Enter a potential password:')
    while True:
        m = input()
        mo = passwordRegex.search(m) 
        if (not mo):
           print('''
Your password should have at least one special charachter,
two digits, two uppercase and three lowercase charachter. Length: 8+ ch-ers.

Enter another password:''')          
        else:
           print('Password is strong')
           return
userInputPasswordCheck()

0

비밀번호는 다음 4 가지 복잡성 규칙 중 3 가지 이상을 충족해야합니다.

[대문자 1 개 이상 (AZ) 문자 1 개 이상 (az) 문자 1 자리 이상 1 자리 이상 (0-9) 하나 이상의 특수 문자-공백도 특수 문자로 취급하는 것을 잊지 마십시오]

10 자 이상

최대 128 자

한 행에 동일한 문자가 2자를 넘지 않아야합니다 (예 : 111은 허용되지 않음)

'^ (?!. (.) \ 1 {2}) ((? =. [az]) (? =. [AZ]) (? =. [0-9]) | (? =. [az] ) (? =. [AZ]) (? =. [^ a-zA-Z0-9]) | (? =. [AZ]) (? =. [0-9]) (? =. [^ a -zA-Z0-9]) | (? =. [az]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])). {10,127} $ '

(?!. * (.) \ 1 {2})

(? =. [az]) (? =. [AZ]) (? =. * [0-9])

(? =. [az]) (? =. [AZ]) (? =. * [^ a-zA-Z0-9])

(? =. [AZ]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])

(? =. [az]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])

. {10.127}


0

위의 모든 정규 표현식은 불행히도 나를 위해 일하지 않았습니다. 강력한 비밀번호의 기본 규칙은 다음과 같습니다.

  • 대문자를 포함해야합니다
  • 최소 소문자를 포함해야합니다
  • 최소한 숫자를 포함해야합니다
  • 최소한 특수 문자를 포함해야합니다
  • 그리고 최소 길이

따라서 최고의 정규식은

^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*]).{8,}$

위 정규식의 최소 길이는 8입니다. {8,}에서 { any_number ,} (으)로 변경할 수 있습니다.

규칙 수정?

최소 x 자 소문자, y 자 대문자, z 자 숫자, 총 최소 길이 w 를 원한다고 가정 해 봅시다 . 그런 다음 정규 표현식 아래에서 시도하십시오.

^(?=.*[a-z]{x,})(?=.*[A-Z]{y,})(?=.*[0-9]{z,})(?=.*[!@#\$%\^&\*]).{w,}$

참고 : 정규식에서 x , y , z , w 변경

편집 : 정규식 답변 업데이트

Edit2 : 수정 사항 추가


귀하의 정규식이 일치되어 12345678당신이이 확신하는 강력한 암호? 게시하기 전에 정규식을 사용해보십시오.
Toto

더 낫지 만 질문에 대답하지는 않지만 1) 8 자 길이를 원합니다. 대문자 2) 2 글자. 3) 1 개의 특수 문자 (! @ # $ & *). 4) 2 개의 숫자 (0-9). 5) 소문자 3 자.
Toto

@ 토토 지금 의견을 공유해 주시겠습니까?
Juned Khatri

정규 표현식은 2 개의 필수 대문자가 다른 문자로 분리 될 수 있다는 것을 고려하지 않습니다. 소문자와 숫자에 대해서도 마찬가지입니다. 유효한 답변은 수락 된 것입니다.
Toto
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.