对数字密码进行排名的算法?
Algorithm to rank numeric passcode?
我正在研究需要获取用户 PIN 码的(移动)应用程序:
6/8 密码的数字 "passcode",输入类似 UI:
因此,在注册步骤中,用户配置他的一个密码(因为这将是一个密码)。
假设密码必须具有固定大小(比如 8 个密码:********)
我的问题与 verify/check 用户选择的数字的可能算法有关,在重复密码或标准密码模式(12345678
、00001111
的情况下给出不好的排名), 很容易被恶意破解者预测...
对这种算法有什么想法吗?
乍一看,该算法可能会阻止(排名不佳)包含重复密码的密码,类似于:
00117788
88886611
或"usual" ascending/descending 模式为:
12345678
98765432
或与个人相关的数字模式,以我为例,我出生于 1963 年 9 月 2 日,因此使用密码可能是个坏主意:
02091963
相反,在我看来 "good" 的序列可能是以下一个:
18745098
90574808
07629301
附带问题:您认为假设 8 个密码的数字密码可以作为 "password" 验证支付交易的可接受解决方案吗?
顺便说一句,我在 Ruby.
中编码
感谢您的耐心等待!
乔治
对于您的前 2 个案例:
字符串中重复的连续字符数:
str = "00117788"
str.chars.each_cons(2).select {|a,b| a == b}.count
#=> 4
或者正如@CarySwoveland 指出的那样,这将产生相同的结果
str.size - str.squeeze.size
#=> 4
增加的字符数
str = "12345678"
str.chars.map(&:to_i).each_slice(2).select {|a,b| (a + 1) == b || (a - 1) == b }.count
#=> 4
#note this will also return 4 for "12563478"
# you could also use str.chars.map(&:to_i).each_cons(2).select {|a,b| (a + 1) == b || (a - 1) == b }.count
# This will return 7 for "12345678" and still return 4 for "12563478"
你也可以把上面的两个结合起来
str = "00117788"
str.chars.map(&:to_i).each_cons(2).select {|a,b| (a + 1) == b || (a - 1) == b || a == b }.count
#=> 6
至于 "personal" 问题,如果您有生日,那么像这样简单的事情应该可行:
require 'date'
birth_day = Date.new(1963,9,2)
str = "02091963"
str == birth_day.strftime("%d%m%Y")
#=> true
尽管对于最后一个,我建议比较多种格式,例如%Y%m%d
和 %m%d%Y
等你甚至可以做类似
str.chars.sort == birth_day.strftime("%d%m%Y").chars.sort
#=> true
确保他们不只是以某种混乱的格式使用这些数字。
希望这能帮助您入门,因为我不知道您对 "good" 和 "bad" 的阈值是多少,这些只是检查值的建议。尽管 "good" 的定义似乎不应该是 "bad"。有点像有效性检查。
如果我使用方法 1 和 2(或组合方法)建议分数 < 4 && 而不是 birth_day 数字的分类可能就足够了,例如
def tester(str,birth_date)
return false if ![6,8].include?(str.size)
b_day = birth_date.strftime("%Y%m%d").chars.sort
str.chars.map(&:to_i).each_cons(2).select do |a,b|
(a + 1) == b ||
(a - 1) == b ||
a == b
end.count < 4 && b_day != str.chars.sort
end
tester("00112233",Date.new(1963,9,2))
#=> false
tester("18745098",Date.new(1963,9,2))
#=> true
似乎适用于您的示例
arry = ["00117788","88886611","12345678","98765432","02091963","18745098","90574808","07629301"]
Hash[arry.map{|v| [v,tester(v,Date.new(1963,9,2))]}]
#=>=> {"00117788"=>false, "88886611"=>false,
"12345678"=>false, "98765432"=>false,
"02091963"=>false, "18745098"=>true,
"90574808"=>true, "07629301"=>true}
我正在研究需要获取用户 PIN 码的(移动)应用程序: 6/8 密码的数字 "passcode",输入类似 UI:
因此,在注册步骤中,用户配置他的一个密码(因为这将是一个密码)。
假设密码必须具有固定大小(比如 8 个密码:********)
我的问题与 verify/check 用户选择的数字的可能算法有关,在重复密码或标准密码模式(12345678
、00001111
的情况下给出不好的排名), 很容易被恶意破解者预测...
对这种算法有什么想法吗?
乍一看,该算法可能会阻止(排名不佳)包含重复密码的密码,类似于:
00117788
88886611
或"usual" ascending/descending 模式为:
12345678
98765432
或与个人相关的数字模式,以我为例,我出生于 1963 年 9 月 2 日,因此使用密码可能是个坏主意:
02091963
相反,在我看来 "good" 的序列可能是以下一个:
18745098
90574808
07629301
附带问题:您认为假设 8 个密码的数字密码可以作为 "password" 验证支付交易的可接受解决方案吗?
顺便说一句,我在 Ruby.
中编码感谢您的耐心等待!
乔治
对于您的前 2 个案例:
字符串中重复的连续字符数:
str = "00117788"
str.chars.each_cons(2).select {|a,b| a == b}.count
#=> 4
或者正如@CarySwoveland 指出的那样,这将产生相同的结果
str.size - str.squeeze.size
#=> 4
增加的字符数
str = "12345678"
str.chars.map(&:to_i).each_slice(2).select {|a,b| (a + 1) == b || (a - 1) == b }.count
#=> 4
#note this will also return 4 for "12563478"
# you could also use str.chars.map(&:to_i).each_cons(2).select {|a,b| (a + 1) == b || (a - 1) == b }.count
# This will return 7 for "12345678" and still return 4 for "12563478"
你也可以把上面的两个结合起来
str = "00117788"
str.chars.map(&:to_i).each_cons(2).select {|a,b| (a + 1) == b || (a - 1) == b || a == b }.count
#=> 6
至于 "personal" 问题,如果您有生日,那么像这样简单的事情应该可行:
require 'date'
birth_day = Date.new(1963,9,2)
str = "02091963"
str == birth_day.strftime("%d%m%Y")
#=> true
尽管对于最后一个,我建议比较多种格式,例如%Y%m%d
和 %m%d%Y
等你甚至可以做类似
str.chars.sort == birth_day.strftime("%d%m%Y").chars.sort
#=> true
确保他们不只是以某种混乱的格式使用这些数字。
希望这能帮助您入门,因为我不知道您对 "good" 和 "bad" 的阈值是多少,这些只是检查值的建议。尽管 "good" 的定义似乎不应该是 "bad"。有点像有效性检查。
如果我使用方法 1 和 2(或组合方法)建议分数 < 4 && 而不是 birth_day 数字的分类可能就足够了,例如
def tester(str,birth_date)
return false if ![6,8].include?(str.size)
b_day = birth_date.strftime("%Y%m%d").chars.sort
str.chars.map(&:to_i).each_cons(2).select do |a,b|
(a + 1) == b ||
(a - 1) == b ||
a == b
end.count < 4 && b_day != str.chars.sort
end
tester("00112233",Date.new(1963,9,2))
#=> false
tester("18745098",Date.new(1963,9,2))
#=> true
似乎适用于您的示例
arry = ["00117788","88886611","12345678","98765432","02091963","18745098","90574808","07629301"]
Hash[arry.map{|v| [v,tester(v,Date.new(1963,9,2))]}]
#=>=> {"00117788"=>false, "88886611"=>false,
"12345678"=>false, "98765432"=>false,
"02091963"=>false, "18745098"=>true,
"90574808"=>true, "07629301"=>true}