2012年12月18日 星期二

密碼強度檢查方式比較

在http://www.checkio.org/上參加了用python解題的遊戲
第一個題目就讓我很感興趣
題目是要寫一隻程式去檢查密碼的強度
條件一:字串長度大於10
條件二:必需包含數字
條件三:必需包含小寫字母
條件四:必需包含大寫字母
我的解法是method1,但看了其他人的解法後不知道效率如何
於是寫了下面的程式去比較
其他的方法是依別人的解法去稍做修改,儘量不修改到程式,以求測試正確
#!/usr/bin/env python

import re
import string
import timeit

data_list = ['A1213pokl', 'bAse730onE', 'asasasasasasasaas', 'QWERTYqwerty', '123456123456', 'QwErTy911poqqqq']

def method1():
    global data_list

    for str in data_list:
        if len(str) >= 10 and re.match('.*([0-9]){1,}.*', str) and re.match('.*([a-z]){1,}.*', str) and re.match('.*([A-Z]){1,}.*', str):
            pass
        else:
            pass

    return True

def method2():
    global data_list

    for str in data_list:
        if len(str) >= 10 and filter(lambda a:a.isupper(), str) and filter(lambda a:a.islower(), str) and filter(lambda a:a.isdigit(), str):
            pass
        else:
            pass

    return True

def method3():
    global data_list

    for str in data_list:
        digit = upper = lower = False

        if len(str) < 10:
           pass
        else:
            for s in str:
                if s in string.ascii_lowercase:
                   lower = True
                if s in string.ascii_uppercase:
                    upper = True
                if s in string.digits:
                    digit = True
            if lower and upper and digit:
                pass
            else:
                pass

    return True

def method4():
    global data_list

    expr = re.compile("^.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$")

    for str in data_list:
        bool(expr.findall(str))

    return True

def method5():
    global data_list

    for str in data_list:
        bool(re.match('((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{10})', str))

    return True

def method6():
    global data_list

    expr = re.compile('((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{10})')

    for str in data_list:
        bool(expr.match(str))

    return True

t = timeit.Timer(method1)
print "method1", t.timeit()

t = timeit.Timer(method2)
print "method2", t.timeit()

t = timeit.Timer(method3)
print "method3", t.timeit()

t = timeit.Timer(method4)
print "method4", t.timeit()

t = timeit.Timer(method5)
print "method5", t.timeit()

t = timeit.Timer(method6)
print "method6", t.timeit()

測試出來的結果
method1 22.0549740791
method2 28.7450380325
method3 24.3238689899
method4 15.9753398895
method5 12.3819229603
method6 7.79946398735

所以看來使用正規表示式理論上是比較快的
但是前提是要看得懂
如果需要對大量的資料做正規表示式的比對
使用re.compile後的結果速度會快很多
但只有少數使用我想差距不大吧
但究竟是多少數,可能還要看正規表示式的內容跟數量才能做決定吧!

2 則留言:

  1. Hi,

    看了你 compile 後速度快很多

    不過這個是 python 的例子

    我還請問一下

    php 裡面有沒有類似的功能,用 perl 的正規

    回覆刪除
  2. PHP的正規表式示檢查都是用perg_grep之類的function

    回覆刪除