破解银行帐户的密码!


64

介绍

为了防止键盘记录程序窃取用户密码,某些银行帐户系统已实施以下安全措施:每次仅提示输入某些数字。

例如,假设您的目标密码为89097,系统可能会提示他们输入第二,第四和第五位数字:

997

或者它可能提示他们输入第一,第三和第五位数字:

807

您所知道的只是您的目标按顺序输入了数字,但是您不知道它们在实际密码中属于哪个位置。您所知道的是有两个9,必须在7之前。并且8在0之前,而0在7之前。因此,有六个可能的密码:

80997
89097
89907
98097
98907
99807

目标计算机上的键盘记录程序已经收集了几个月的密码,所以让我们开始吧!

挑战

给定一个三位数的输入列表,输出对所有输入都有效的所有可能的密码。为了降低计算复杂度并减少可能的结果数量,请确保密码为数字且固定大小为5。每个输入中的数字顺序如下:如果是123,则目标首先键入1,然后2,然后3。

输入/输出示例

|----------------------|--------------------------------------------|
|         Input        |                   Output                   |
|----------------------|--------------------------------------------|
| [320, 723, 730]      | [37230, 72320, 73203, 73230]               |
| [374, 842]           | [37842, 38742, 83742]                      |
| [010, 103, 301]      | [30103]                                    |
| [123, 124, 125, 235] | [12345, 12354, 12435]                      |
| [239, 944]           | [23944]                                    |
| [111, 120]           | [11201, 11120, 11210, 12011, 12110, 12101] |
| [456, 789]           | []                                         |
| [756, 586]           | [07586, 17586, 27586, 37586, 47586, 57586, 57856, 58756, 67586, 70586, 71586, 72586, 73586, 74586, 75086, 75186, 75286, 75386, 75486, 75586, 75686, 75786, 75806, 75816, 75826, 75836, 75846, 75856, 75860, 75861, 75862, 75863, 75864, 75865, 75866, 75867, 75868, 75869, 75876, 75886, 75896, 75986, 76586, 77586, 78586, 79586, 87586, 97586] |
| [123]                | [00123, 01023, 01123, 01203, 01213, 01223, 01230, 01231, 01232, 01233, 01234, 01235, 01236, 01237, 01238, 01239, 01243, 01253, 01263, 01273, 01283, 01293, 01323, 01423, 01523, 01623, 01723, 01823, 01923, 02123, 03123, 04123, 05123, 06123, 07123, 08123, 09123, 10023, 10123, 10203, 10213, 10223, 10230, 10231, 10232, 10233, 10234, 10235, 10236, 10237, 10238, 10239, 10243, 10253, 10263, 10273, 10283, 10293, 10323, 10423, 10523, 10623, 10723, 10823, 10923, 11023, 11123, 11203, 11213, 11223, 11230, 11231, 11232, 11233, 11234, 11235, 11236, 11237, 11238, 11239, 11243, 11253, 11263, 11273, 11283, 11293, 11323, 11423, 11523, 11623, 11723, 11823, 11923, 12003, 12013, 12023, 12030, 12031, 12032, 12033, 12034, 12035, 12036, 12037, 12038, 12039, 12043, 12053, 12063, 12073, 12083, 12093, 12103, 12113, 12123, 12130, 12131, 12132, 12133, 12134, 12135, 12136, 12137, 12138, 12139, 12143, 12153, 12163, 12173, 12183, 12193, 12203, 12213, 12223, 12230, 12231, 12232, 12233, 12234, 12235, 12236, 12237, 12238, 12239, 12243, 12253, 12263, 12273, 12283, 12293, 12300, 12301, 12302, 12303, 12304, 12305, 12306, 12307, 12308, 12309, 12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317, 12318, 12319, 12320, 12321, 12322, 12323, 12324, 12325, 12326, 12327, 12328, 12329, 12330, 12331, 12332, 12333, 12334, 12335, 12336, 12337, 12338, 12339, 12340, 12341, 12342, 12343, 12344, 12345, 12346, 12347, 12348, 12349, 12350, 12351, 12352, 12353, 12354, 12355, 12356, 12357, 12358, 12359, 12360, 12361, 12362, 12363, 12364, 12365, 12366, 12367, 12368, 12369, 12370, 12371, 12372, 12373, 12374, 12375, 12376, 12377, 12378, 12379, 12380, 12381, 12382, 12383, 12384, 12385, 12386, 12387, 12388, 12389, 12390, 12391, 12392, 12393, 12394, 12395, 12396, 12397, 12398, 12399, 12403, 12413, 12423, 12430, 12431, 12432, 12433, 12434, 12435, 12436, 12437, 12438, 12439, 12443, 12453, 12463, 12473, 12483, 12493, 12503, 12513, 12523, 12530, 12531, 12532, 12533, 12534, 12535, 12536, 12537, 12538, 12539, 12543, 12553, 12563, 12573, 12583, 12593, 12603, 12613, 12623, 12630, 12631, 12632, 12633, 12634, 12635, 12636, 12637, 12638, 12639, 12643, 12653, 12663, 12673, 12683, 12693, 12703, 12713, 12723, 12730, 12731, 12732, 12733, 12734, 12735, 12736, 12737, 12738, 12739, 12743, 12753, 12763, 12773, 12783, 12793, 12803, 12813, 12823, 12830, 12831, 12832, 12833, 12834, 12835, 12836, 12837, 12838, 12839, 12843, 12853, 12863, 12873, 12883, 12893, 12903, 12913, 12923, 12930, 12931, 12932, 12933, 12934, 12935, 12936, 12937, 12938, 12939, 12943, 12953, 12963, 12973, 12983, 12993, 13023, 13123, 13203, 13213, 13223, 13230, 13231, 13232, 13233, 13234, 13235, 13236, 13237, 13238, 13239, 13243, 13253, 13263, 13273, 13283, 13293, 13323, 13423, 13523, 13623, 13723, 13823, 13923, 14023, 14123, 14203, 14213, 14223, 14230, 14231, 14232, 14233, 14234, 14235, 14236, 14237, 14238, 14239, 14243, 14253, 14263, 14273, 14283, 14293, 14323, 14423, 14523, 14623, 14723, 14823, 14923, 15023, 15123, 15203, 15213, 15223, 15230, 15231, 15232, 15233, 15234, 15235, 15236, 15237, 15238, 15239, 15243, 15253, 15263, 15273, 15283, 15293, 15323, 15423, 15523, 15623, 15723, 15823, 15923, 16023, 16123, 16203, 16213, 16223, 16230, 16231, 16232, 16233, 16234, 16235, 16236, 16237, 16238, 16239, 16243, 16253, 16263, 16273, 16283, 16293, 16323, 16423, 16523, 16623, 16723, 16823, 16923, 17023, 17123, 17203, 17213, 17223, 17230, 17231, 17232, 17233, 17234, 17235, 17236, 17237, 17238, 17239, 17243, 17253, 17263, 17273, 17283, 17293, 17323, 17423, 17523, 17623, 17723, 17823, 17923, 18023, 18123, 18203, 18213, 18223, 18230, 18231, 18232, 18233, 18234, 18235, 18236, 18237, 18238, 18239, 18243, 18253, 18263, 18273, 18283, 18293, 18323, 18423, 18523, 18623, 18723, 18823, 18923, 19023, 19123, 19203, 19213, 19223, 19230, 19231, 19232, 19233, 19234, 19235, 19236, 19237, 19238, 19239, 19243, 19253, 19263, 19273, 19283, 19293, 19323, 19423, 19523, 19623, 19723, 19823, 19923, 20123, 21023, 21123, 21203, 21213, 21223, 21230, 21231, 21232, 21233, 21234, 21235, 21236, 21237, 21238, 21239, 21243, 21253, 21263, 21273, 21283, 21293, 21323, 21423, 21523, 21623, 21723, 21823, 21923, 22123, 23123, 24123, 25123, 26123, 27123, 28123, 29123, 30123, 31023, 31123, 31203, 31213, 31223, 31230, 31231, 31232, 31233, 31234, 31235, 31236, 31237, 31238, 31239, 31243, 31253, 31263, 31273, 31283, 31293, 31323, 31423, 31523, 31623, 31723, 31823, 31923, 32123, 33123, 34123, 35123, 36123, 37123, 38123, 39123, 40123, 41023, 41123, 41203, 41213, 41223, 41230, 41231, 41232, 41233, 41234, 41235, 41236, 41237, 41238, 41239, 41243, 41253, 41263, 41273, 41283, 41293, 41323, 41423, 41523, 41623, 41723, 41823, 41923, 42123, 43123, 44123, 45123, 46123, 47123, 48123, 49123, 50123, 51023, 51123, 51203, 51213, 51223, 51230, 51231, 51232, 51233, 51234, 51235, 51236, 51237, 51238, 51239, 51243, 51253, 51263, 51273, 51283, 51293, 51323, 51423, 51523, 51623, 51723, 51823, 51923, 52123, 53123, 54123, 55123, 56123, 57123, 58123, 59123, 60123, 61023, 61123, 61203, 61213, 61223, 61230, 61231, 61232, 61233, 61234, 61235, 61236, 61237, 61238, 61239, 61243, 61253, 61263, 61273, 61283, 61293, 61323, 61423, 61523, 61623, 61723, 61823, 61923, 62123, 63123, 64123, 65123, 66123, 67123, 68123, 69123, 70123, 71023, 71123, 71203, 71213, 71223, 71230, 71231, 71232, 71233, 71234, 71235, 71236, 71237, 71238, 71239, 71243, 71253, 71263, 71273, 71283, 71293, 71323, 71423, 71523, 71623, 71723, 71823, 71923, 72123, 73123, 74123, 75123, 76123, 77123, 78123, 79123, 80123, 81023, 81123, 81203, 81213, 81223, 81230, 81231, 81232, 81233, 81234, 81235, 81236, 81237, 81238, 81239, 81243, 81253, 81263, 81273, 81283, 81293, 81323, 81423, 81523, 81623, 81723, 81823, 81923, 82123, 83123, 84123, 85123, 86123, 87123, 88123, 89123, 90123, 91023, 91123, 91203, 91213, 91223, 91230, 91231, 91232, 91233, 91234, 91235, 91236, 91237, 91238, 91239, 91243, 91253, 91263, 91273, 91283, 91293, 91323, 91423, 91523, 91623, 91723, 91823, 91923, 92123, 93123, 94123, 95123, 96123, 97123, 98123, 99123] |
|----------------------|--------------------------------------------|

规则

  • 输入保证为非空。
  • 前导零和尾随零很重要:01234与不同12340,并且1234不会破解任何一个密码。想想真正的密码是如何工作的!
  • 标准I / O规则适用。
  • 没有标准漏洞
  • 这是,因此最短的答案以字节为单位。欢迎使用非编码语言!

5
这些数字是否总是井井有条?基于测试用例,我认为它们是正确的,但是除非阅读了它,否则我看不到规则中提到它。
Kevin Cruijssen

13
欢迎来到PPCG!这是一个不错的,结构合理且格式整齐的第一个挑战。到目前为止,您显然已经完成了功课。我期待回答(如果有人没有先在R中回答!)。将来,我们建议使用沙箱在发布到main之前获取反馈。希望您在PPCG上度过愉快的时光!
朱塞佩

1
@Giuseppe谢谢!多年来,我一直在匿名阅读此站点上的问题,并且我已经进行了几个月的写作和调整,并实际上解决了此特定问题:我非常喜欢它,可以跳过沙箱。下次我会先贴在那里!
cefel

2
@Arnauld好吧,如果您的密码是01234或12340,则不能通过键入1234登录。密码至少是一个数字,而不是一个数字,即使是由数字组成。所以是的,前导零和尾随零是强制性的。
cefel

2
最终测试用例似乎丢失了22123 ...除非我误会了什么?
乔纳

Answers:


24

Python,100字节

lambda e,d='%05d':[d%i for i in range(10**5)if all(re.search('.*'.join(x),d%i)for x in e)]
import re

在线尝试!

在Python 2和Python 3中均可使用。

(Python 3.8中为97个字节 :)

lambda e:[p for i in range(10**5)if all(re.search('.*'.join(x),p:='%05d'%i)for x in e)]
import re

1
这是一个很好的解决方案……
约拿

1
您的非3.8代码可以执行别名“ string”的“穷人的赋值表达式” '%05d'
xnor

22

05AB1E11 9字节

žh5ãʒæIåP

在线尝试!

说明

žh          # push 0123456789
  5ã        # 5 times cartesian product
    ʒ       # filter, keep only values are true under:
     æ      # powerset of value
      Iå    # check if each of the input values are in this list
        P   # product

12

JavaScript(ES6),88个字节

使用打印结果alert()

a=>{for(k=n=1e5;n--;)a.every(x=>(s=([k]+n).slice(-5)).match([...x].join`.*`))&&alert(s)}

在线尝试!

已评论

a => {                    // a[] = input array of 3-character strings
  for(k = n = 1e5; n--;)  // initialize k to 100000; for n = 99999 to 0:
    a.every(x =>          // for each string x = 'XYZ' in a[]:
      ( s =               //   define s as the concatenation of
          ([k] + n)       //   '100000' and n; e.g. '100000' + 1337 -> '1000001337'
          .slice(-5)      //   keep the last 5 digits; e.g. '01337'
      ).match(            //   test whether this string is matching
        [...x].join`.*`   //   the pattern /X.*Y.*Z/
      )                   //
    ) &&                  // end of every(); if all tests were successful:
      alert(s)            //   output s
}                         //

8

Haskell,81 80 78 76字节

f x=[p|p<-mapM(:['1'..'9'])"00000",all(`elem`(concat.words<$>mapM(:" ")p))x]

Haskell中一种明显的暴力破解方法:建立一个所有可能密码的列表,并将那些来自输入列表的所有元素都放在相应子序列列表中的密码。

在线尝试!

编辑:-1个字节感谢@xnor ,-2 -4个字节感谢@ H.PWiz


1
看起来您可以自己计算出子序列短一点。
xnor

1
concat.words<$>mapM(:" ")p
H.PWiz

3
用于p<-mapM(:['1'..'9'])"00000"保存另外2个字节
H.PWiz


5

Pyth,11个字节

f<QyT^s`MT5

将输入作为一组字符串。
在这里尝试

说明

f<QyT^s`MT5
      s`MT      Take the digits as a string.
     ^    5     Take the Cartesian product with itself 5 times.
f   T           Filter the ones...
 <Qy            ... where the input is a subset of the power set.


5

Python 3,98字节

f=lambda l,s='':any(l)or print(s)if s[4:]else[f([x[x[:1]==c:]for x in l],s+c)for c in'0123456789']

在线尝试!

递归地尝试在中建立每个五位数的数字字符串s,跟踪l仍要命中的子序列。如果最后都为空,则打印结果。

Python 3.8(预发布),94字节

lambda l:[s for n in range(10**5)if all(''in[x:=x[x[:1]==c:]for c in(s:='%05d'%n)]for x in l)]

在线尝试!

看一下赋值表达式的力量!使用此处方法检查子序列。



4

视网膜,53字节

~(`
.$*
m`^
G`
^
K`¶5+%`$$¶0"1"2"3"4"5"6"7"8"9¶
"
$$"

在线尝试!说明:

~(`

执行脚本后,将结果作为新脚本并执行。

.$*

.*随处插入。这导致.*3.*2.*0.*虽然我们只需要3.*2.*0,但这并不重要。

m`^
G`

G`在每行的开头插入一个。这将其转换为Retina Grep命令。

^
K`¶5+%`$$¶0"1"2"3"4"5"6"7"8"9¶
"
$$"

在前面再加上两个Retina命令。因此,生成的脚本将如下所示:

K`

清除缓冲区(包含原始输入)。

5+

重复5次...

%`$

...附加到每一行...

0$"1$"2$"3$"4$"5$"6$"7$"8$"9

...数字0,然后是行的副本,然后是数字1,依此类推,直到9。这意味着n循环后您将拥有全n数字。

G`.*3.*2.*0.*
G`.*7.*2.*3.*
G`.*7.*3.*0.*

根据输入内容过滤掉可能的数字。


4

R80 82字节

Reduce(intersect,lapply(gsub("",".*",scan(,"")),grep,sprintf("%05d",0:99999),v=T))

这是使用正则表达式的基本R解决方案。编写这些嵌套的函数系列使我意识到,我已经学到了多少了解magrittr软件包的知识!

最初没有读取输入规则,因此现在从stdin读取(感谢@KirillL)。

在线尝试!


@digEmAll它说是82个字节,不是吗?您不能使用整数,因为输入中可能会出现前导零。
尼克·肯尼迪

抱歉,我读了标题,不知不觉中我选了最小的数字而没有注意到它被删除了……是的,再次抱歉,您对字符串输入是正确的;)
digEmAll

2

红宝石79 77字节

->x{(0...1e5).map{|i|'%05d'%i}.select{|i|x.all?{|c|i=~/#{c.gsub('','.*')}/}}}

在线尝试!

输入是一个字符串数组。

这是相同代码的可读性更高的版本:

def f(codes)
  (0...10**5).map{|i| '%05d'%i}.select do |i|
    codes.all? do |code|
      i =~ Regexp.new(code.chars.join('.*'))
    end
  end
end

顺便说一句,你的方法也可以通过切换通过格式化的上限值,以字符数组的输入,在我的版本,和-2多个字节变短1e5,像这样
基里尔L.

@KirillL。感谢-2个字节。我不会更改输入格式,因为我的答案看起来很像您的答案。干杯!
艾里克·杜米尼尔

2

PHP 128字节

for(;$i++<1e5;$k>$argc||print$s)for($k=0;$n=$argv[++$k];)preg_match("/$n[0].*$n[1].*$n[2]/",$s=sprintf("%05d
",$i-1))||$k=$argc;

要么

for(;$i<1e5;$i+=$k<$argc||print$s)for($k=0;$n=$argv[++$k];)if(!preg_match("/$n[0].*$n[1].*$n[2]/",$s=sprintf("%05d
",$i)))break;

从命令行参数获取输入。运行-nr在线尝试它们



2

Japt,21个字节

1e5o ù'0 f@e_XèZË+".*

试试吧!

1e5o ù'0 f@e_XèZË+".*    # full program

1e5o                     # generate numbers under 100k
     ù'0                 # left pad with 0's
         f@              # filter array
           e_            # check every element of input array
             Xè          # X is the number to be tested.
                         # test it against a regex.
               ZË+".*    # the regex is an element from the input array
                         # with wildcards injected between each character

-2个字节,感谢@Shaggy!


较少的无用变量::1e5o ù'0 fA{Ue@AèX®+".*P
仅ASCII的

同样是23:1e5o ù'0 fA{Ue@AèX¬q".*
仅使用ASCII


有趣的是...我没意识到return X,Y,Z会选上学期。感谢您的提示:)
dana

1
@dana; 是的,这是JavaScript的功能:tio.run/##y0osSyxOLsosKNHNy09J/Z9m@1@jQqdS09auuii1pLQoTwHIq/…
毛茸茸的

2

C#(Visual C#交互式编译器),116字节

x=>{for(int i=0;i<1e5;){var s=$"{i++:D5}";if(x.All(t=>t.Aggregate(-6,(a,c)=>s.IndexOf(c,a<0?a+6:a+1))>0))Print(s);}}

在线尝试!

// x: input list of strings
x=>{
  // generate all numbers under 100k
  for(int i=0;i<1e5;){
    // convert the current number to
    // a 5 digit string padded with 0's
    var s=$"{i++:D5}";
    // test all inputs against the 5 digit
    // string using an aggregate.
    // each step of the aggregate gets
    // the index of the next occurrence
    // of the current character starting
    // at the previously found character.
    // a negative index indicates error.
    if(x.All(t=>t
             .Aggregate(-6,(a,c)=>
               s.IndexOf(c,a<0?a+6:a+1)
             )>0))
      // output to STDOUT
      Print(s);
  }
}

编辑:修复了一个错误,该错误多次计数同一角色。例如,如果000已记录,则此函数用于返回包含单个的所有密码0



1

K 67字节

{n@&{&/y in\:x@/:&:'a@&3=+/'a:(5#2)\:'!32}[;x]'n:{"0"^-5$$x}'!_1e5}

K具有(非常)原始的正则表达式功能,因此我尝试了另一种方法。

{...}定义一个lambda。使用示例:{...}("320";"723";"730")

退货 ("37230";"72320";"73203";"73230")

  • n 是0..9999范围内的整数列表,为0填充的字符串

    • _1e5 将底数应用于浮点1e5(科学计数法)->生成整数100000

    • !_1e5 生成整数列表0..99999

    • {..}'!_1e5 将lambda应用于0..99999中的每个值

    • $x 将参数x(隐式arg)转换为字符串

    • -5$$x右键将字符串$ x调整为大小为5的字段(例如,-5$$12生成" 12"

    • "0"^string用“ 0”字符替换空格,因此"0"^-5$$12生成"00012"

  • a 是0..31范围内的5位值的整数列表

    • !32 产生值0..31

    • (5#2) 重复2次五次(清单2 2 2 2 2)

    • (5#2)\:'!32 为范围0..31中的每个值生成5位值(2基5倍)

  • 我们用正好3个值过滤a的值。这值在哪里模式可以位于所有组合(地方): 11100 11010 11001 10110 10101 10011 01110 01101 01011 00111。例如 对于“ abc”模式,我们与正则表达式等效abc?? ab?c? ab??c a?bc? a?b?c a??bc ?abc? ?ab?c ?a?bc ??abc?

    • +\'a 计算每个二进制表示的总和(个数)

    • 3=+\'a 生成布尔值列表(如果a中的每个值正好有3个值)

    • a@&3=+\'a 读为“在3 = + \'a为真的a”

  • 生成先前位置的索引列表:(0 1 2; 0 1 3; 0 1 4; 0 2 3; 0 2 4; 0 3 4; 1 2 3; 1 2 4; 1 3 4; 2 3 4)以及密码的可能输入值(x)

    • &:' 读取为“其中每个”,应用于二进制编码的整数列表,并计算每个1位的索引

    • x@/: 将密码x应用于索引列表的每个元素(生成所有可能的输入值)

  • 确定是否所有模式都位于所有可能输入值的列表中

    • y 是表示模式列表的arg

    • y in\: 读取为右侧列表中y的每个值

    • &/是“结束”。&/y in\:..如果y中的所有模式都位于列表中,则返回true。

  • 最后,在使lambda为true的每个索引处返回n中的每个字符串

    • n@&{..} 读为“ n在lambda {..}返回true的位置”

0

C(GCC)222字节

#define C(p)*f-p?:++f;
#define I(x,y)x<10?:++y,x%=10;
a,b,c,d,e;f(int**H){for(;a<10;){int**h=H,*f,g=0;for(h=H;*h;){f=*h;C(a)C(b)C(c)C(d)C(e)f>*h+++2?:(g=1);}g?:printf("%d%d%d%d%d,",a,b,c,d,e);++e;I(e,d)I(d,c)I(c,b)I(b,a)}}

在线尝试

呼叫码

int main() {
  int hint1[5] = {9,9,7,-1,-1};
  int hint2[5] = {8,0,7,-1,-1};
  int* hints[3] = {hint1,hint2,0};
  f(hints);
}

输出量

80997,89097,89907,98097,98907,99807,

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.