密码的重要性毋庸多言,尤其是在当今人们越来越离不开互联网的情况之下。最近各种密码泄露事件层出不穷,社工技术也是比想象中厉害很多。虽说密码的原则,例如不要重复啊,要复杂啊,大家都知道,然而真正能做到的人也是少数,大多数仍然是偷懒几个密码走天下。然而这终究不是长久之计,因此一些密码管理工具诸如 1Password, LastPass 等开始流行起来。这类工具一般的做法是需要你设定一个主密码,进入后就可以查看各个网站的单独密码,也可以为你生成比较安全的密码,这样比较灵活。但它们仍然需要在本地保存各种密码(或许是用主密码作为 key 的对称加密?),并且会把这些信息加密后保存在网上。然而需要保存密码本身加之安全性全系于主密码一身,仍让人对其可靠性产生担忧。于是突发奇想,能否设计一套密码管理机制,使得我们并不需要保存每个密码,而是在需要时由其实时计算而出。
初步设想
在这个机制中,用户输入一个自定义 key,得到一个输出,即计算出来的密码。密码计算出后可以自动复制到剪贴板,用户不需要知道密码的具体内容。
假设存在这样一个系统,那么它需要保证:
- 针对不同的网站,需要生成不同的密码。这个可以通过自定义 key 来保证。
- 对于同样的自定义 key,不同的用户得到的密码应当不同。否则 key 实质就成了密码。
这个机制不需要联网,也不需要本地存储各种密码。key 实质就是一个助记符,用户需要将它记在心中,但相比于各种复杂密码,记忆的难度已经大大降低。此外,它不应该被除主人外的其他人使用,否则其他人只要知道了主人的各个 key,也就相当于知道了密码。为此我们仍然需要一个主密码。不过和传统意义上的主密码不同,由于我们的机制并不记录密码或联网,我们并不能验证主密码的正确性,而是将主密码和自定义 key 共同组成算法的输入。这样他人即使知道了主人的 key,但因为不知道主密码,得到的输出也将是错误的。为此,虽然不是必需(因为主密码只是参与运算的一个普通字符串),我们仍然建议主密码足够复杂(例如包含数字、大小写字母、特殊符号且足够长)以至于难以猜测(因为自定义 key 为了方便记忆必然是容易被猜到的)。
让我们回到上文的第二点,因为同样的输入必然需要得到同样的输出,而算法本身并不能改变,除非你对每个用户都特殊定制一个软件。也不能使用什么元编程之类的手段,因为若不直接编译好,就等于公开了你的计算算法从而增加被破解的可能性。最简单的方法便是在用户第一次使用时产生一个随机数或者 UUID 加入输入。不过加入了主密码以后也就相当于解决了这个问题。然而主密码是用户自己选取的,仍然存在重复的可能,因此保险起见仍然可以加入随机数或者 UUID,将重复概率降低到约等于 0。
如何更换单个密码
更换单个密码是一个常用功能,假如怀疑某个密码遭遇到泄露可以方便地重置它而不影响其他密码。目前我们使用主密码 + key + 一次生成的随机数来唯一确定一个密码。最简单的想法是用户修改自己的 key 就行。然而 key 作为助记符,若是频繁修改,也会给用户带来记忆上的困难。而修改主密码和随机数即意味着所有的密码都要进行修改,这显然是无法接受的。照道理应该通过修改随机数实现,但为了不影响其他密码,我们必须建立每个 key 和随机数之间的映射关系,即需要保存这些 key 和对应的随机数,而这却恰恰是设计之初想要极力避免的。
为此需要设计一个妥协的方案,目前的设想如下:生成一个随机数的表,这不得不保存为文件。另外将 key 和对应的随机数组合,通过非对称加密后保存为文件(可以进一步通过改变组合方式、加 salt 等增加安全性)。这样即使文件被他人得到也无法破译出 key 及对应关系。软件工作时也无从得知,而是需要穷举随机数表,加密后比对,才能确定该 key 对应了哪个随机数。此外,对于大多数密码而言,它们永远不会变化,即不需要使用新的随机数,也就不需要保存在文件中。对于一些特定的重要密码,用户也可以选择修改自己记忆中的 key 值,通过增加记忆成本来降低风险。
多端的数据一致性
需要输入密码的场合,电脑端仍是大头,然而手机端也越来越需要了,为此需要开发手机上能用的版本。移植工作简单,但对于这样一个非联网的密码管理工具,如何才能保证电脑上和手机上得到的密码是一样的?自然主密码, key 和算法都是一样的,那么只需要保证随机数表相同。然而你不能要求用户来同步整个随机数表。容易想到,我们只需要系统生成一个 appkey,再由算法利用这个 appkey 生成整个随机数表即可。用户在一个新的端第一次使用时需要输入这个 appkey,这样问题解决。
软件升级
理想状态下只要做出来就永远不会改变,然而信息技术的发展日新月异,也不能预测这个工具中使用的各种算法等是否需要更改。一旦更改则用户的全部密码都需要改变,而用户很难记起自己通过这一工具“保存”了多少密码。在此提个可行的解决方法:使用时双开前后两个版本,先用新版本得到的密码尝试,若错误则说明该网站的密码依然需要通过旧版本得到,此时用户应当及时修改密码为新版本。长此以往所有密码均被修改,版本过渡完成。
总结
相比于目前常用的密码管理工具,本工具不联网,不保存,减少密码本身被简单泄露的危险。但也丢失了灵活性,即用户不能保存自定义的密码,而是只能用计算出来的密码。不过一般来说这都是更加安全的,既然选择使用密码管理工具,就应该有这样的安全意识。
这套机制中,用户需要记忆自己的主密码和各网站的 key。工具则需要提供一个随机的 appkey,以及三套算法:通过 appkey 可重复地生成随机数表、非对称加密验证 key 和随机数的对应关系、通过主密码 + key + 随机数可重复地计算出密码。
那么什么时候能做出来呢?待续……