去中心化密码恢复

信息安全 密码 密码学 密码管理 恢复
2021-09-07 13:36:27

在没有集中服务的情况下,是否有良好/成熟的密码/密钥恢复技术?

(一切正常,但我更喜欢将恢复信息分布在多个地方的解决方案)

例如:我可以想象一个生成恢复密钥的系统,使用秘密共享进行拆分并分发,例如

  • 一些零件下载到本地计算机
  • 一些部分通过电子邮件发送给自己
  • 一些零件打印出来并放在保险箱中
  • 一些零件送给朋友保护

这本质上是分布式密钥托管:是否存在一些使用这种方案的现有系统示例?有替代方案吗?有最佳实践吗?

澄清:就个人而言,我相信自己会记住一个相对强的密码——这是设计一个供其他人使用的系统,并不是所有人都有信心这样做。

4个回答

我在您最初的问题下写了一些评论,但我觉得将我的评论(描述解决方案)与迄今为止提到的所有答案结合起来可能会产生您可以实际使用的东西(而不是自己研究)。

正如评论中提到的,拆分密钥技术是制作 X 个子密钥的过程。最常见的实现方式是要求所有 X 子密钥来恢复受保护的密钥。

在我接下来讨论的示例中,我将定义以下单词以确保清晰:

key:静态(又名共享/对称)或基于密码或密码生成的加密变量。

密码:人类通常记住的明文或其他非加密衍生值(或者,可耻的是,写在键盘下的便签上)。

passphrase:就本例而言,passphrase 与密码相同。

sub-key :与被保护的密钥大小相等的单个恢复信息块。

split-key:将恢复密钥分解为各种拆分(又名sub-keychunks)的概念。

字典字符:用户可以输入到恢复机制中的字符集(例如,A-Za-z0-9)。

现在我们已经解决了这个问题,我们可以研究一种方法来实现这个解决方案。

假设我的密码(如上定义)是IKnowThisIsBad

我将密码传递给 OpenSSL Linux bash 命令sha512sum并输出散列值:d3a48c640bbd58633138e2f88b2d3979e3d609df6cd22246dd73d35a77b6755fcf580be431a93c059bc7106ab8d37491d440233908ac728cd46233908a3679d

我使用该哈希值(注意:此时它没有加盐,我试图保持简单......)作为我的key这是我们要保护的密钥,我将这个密钥用于我所有相关的加密目的。

让我们假设我们将通过使用 3个子密钥来保护恢复过程(但是,任何数量大于 1的子密钥都是有效的)。

我们在这里假设用户无法记住这样的序列,因此无法(在他们的脑海中)存储子键尽管如此,为了成功(并且正确地)使用拆分密钥技术,它们必须提供适当长度的我们将再次使用我们的朋友sha512sum在这个例子中,让我们假设用户获取恢复块的密码My Secret Recovery Phrase该迭代的输出产生:196822a43878ff1c263fe16b6cb2d768b157cf1018ded64e6bab4d36822262ff7f61404ab21c2d279c6cfaa85112786044231917c484dcf3a81931d34fa86edd

现在我们需要一个将存储在其他地方的块。使用您的示例,我们会说它作为文本存储到电子邮件中。回到我们的朋友sha512sum来生成这个子键值我们将使用密码电子邮件存储密钥信息不是很安全!!,产生以下值:a8a73e1c6ecd3f2ddff853901f3781fac5839d42cf360833e7148163beb2c05ad5288e6d3c30fd9e7a4bb854b7f507c70991f6c04c507c58028573b5f89ce6a7

此时我们已经生成了三个恢复子密钥中的两个。不管你做了多少sub-key最后一个都是 special如果我们有 10个子键,那么我们可以按照前面的示例创建前 9 个。如果我们有 30 个,那么可以这样创建前 29 个。但无论如何,都会生成一个特殊的值。要创建最后一个恢复子密钥,我们必须将到目前为止的所有已知值进行异或。

让我们更仔细地研究一下。

我们在密码学中使用 XOR 的主要原因是它是可恢复的(与 OR 和 AND 操作不同)。当我们对前面的三个值(即密钥从恢复密码生成的用户恢复子密钥和存储在电子邮件中的子密钥)进行异或运算时,我们生成第三个子密钥,其长度自动与其他 3 个输入。这第三可以分配给您的“下载到本地计算机”恢复选项。这个异或运算的结果(可以认为是:key ^ sub-key 1 ^ sub-key 2 -OR- key XOR sub-key 1 XOR sub-key2) 是:426;94fc5?68`854eaff50ij?gcao?g`d7i2j;add=3af<3`71gehf0dm`26b7fa0511<7g1b`cjgc;g7`a65ibm5>340;l6`9?0d<k?`n40d7a352mm010gk=j8ecfc

对于最后一个输出的奇怪格式,我深表歉意。这是必要的,因为生成的子键值`包含必须特别转义的反引号 ( ) 字符。

此时,我们将最终值保存在“下载到本地计算机”策略指定的某个位置。

伟大的。所以这是一堆散列值,但是如果它从使用它的任何底层系统中丢失,你如何取回你的密钥呢?我们恢复所有子键值并将它们异或在一起。这将重现原始键值

为了证明这一点,我编写了一个小的 Python blob,它为任意数量的 XOR 字符串实现了这个 XOR 操作。在下面找到它。

#!/usr/bin/env python

#KEY:    d3a48c640bbd58633138e2f88b2d3979e3d609df6cd22246dd73d35a77b6755fcf580be431a93c059bc7106ab8d37491d442339879947728d8da436a9c2c60c0
#RECOV1: 196822a43878ff1c263fe16b6cb2d768b157cf1018ded64e6bab4d36822262ff7f61404ab21c2d279c6cfaa85112786044231917c484dcf3a81931d34fa86edd
#RECOV2: a8a73e1c6ecd3f2ddff853901f3781fac5839d42cf360833e7148163beb2c05ad5288e6d3c30fd9e7a4bb854b7f507c70991f6c04c507c58028573b5f89ce6a7
    
#    RECOV3 is generated by running this script with the above 3 command-line values generated by 'sha512sum'
#RECOV3: 426;94fc5?68`854eaff50ij?gcao?g`d7i2j;add=3af<3`71gehf0dm`26b7fa0511<7g1b`cjgc;g7`a65ibm5>340;l6`9?0d<k?`n40d7a352mm010gk=j8ecfc

#    Recovery of KEY is accomplished by running this script with RECOV1 RECOV2 and RECOV3 as parameters.

import sys, binascii, argparse;

parser      = None;
stringlist  = None;


def xor_strings(base, new):
    return "".join(chr(ord(b)^ord(n)) for b, n in zip(base, new));


def SetParseArgs():
    global parser, stringlist;
    
    parser = argparse.ArgumentParser(description="XOR a bunch of strings!");
    parser.add_argument("string", nargs="+");
    stringlist = parser.parse_args().string;


def main():
    global sys, stringlist;
    
    SetParseArgs();

    res = stringlist[0];
    for index in range(len(stringlist) - 1):
        #skip string #1
        hexstr = stringlist[index + 1];
        res = xor_strings(res, hexstr);
    
    print "XOR result string:\n%s" %(res);


if __name__ == "__main__":
    main();
else:
    print "This script cannot be imported";
    print "Please run as: %s <string_1> <string_2> [string_n]" %(sys.argv[0]);
    print "For best (and most logically-correct) results, ensure strings are the same length";

该脚本可以用来创建恢复,但是你要分发它们,然后使用该脚本ALL中的,你会恢复原来的钥匙

这个例子应该清楚地恢复任何小于如何ALL中的是一样没用,因为有他们没有的,因为攻击者仍然要蛮力整个每种可能的组合的地址空间。

我希望你们中的一些人觉得这很有用。我喜欢把它放在一起的练习,现在我自己可能会实际使用它,因为它已经完成了实现!:-)

请评论您观察到的任何错字。我对上述所有示例都使用了文字值,因此运行上述命令/工具的任何人都会产生相同的结果。我将所有 pre-sha512sum 字符串写入单个文本文件,最后没有换行符,并将它们作为参数提供给sha512sum以创建keysub-key 1 和sub-key 2。

感谢并享受!

我不确定我的理解是否正确,但我见过在客户端生成随机令牌的系统,然后在远程服务器上输入验证令牌真实性并生成第二个令牌,输入第二个令牌再次在客户端(或您要恢复的信息所在的任何位置)上,如果密码有效,现在可以重置密码。

也许这会有所帮助。

我认为如果只有您控制这些密码,那么密码管理器确实是您最好的选择。您可以将密码存储在加密的密码数据库文件中。该文件可以存储在云中、赠送给朋友的 USB 以及本地/工作计算机上。

您需要保留或拥有的只是一个强大的数据库密码,并将其保留给自己,您可以有多个恢复选项。在不知道密钥的情况下破解它同样困难,如果不是更困难的话。

如果您只想安全地存储密码并为密码提供安全的备份位置,那么拆分恢复详细信息会变得不必要地复杂。

当您需要让多方聚集在一起以访问敏感材料时,秘密共享非常有用。一种非常简单且不太安全的方法是让您和朋友分别记住一个密码。然后你用你的作为完整密码的第一个组成部分,她用她的作为第二个组成部分。这样,你们俩都拥有分散的密钥组件,但可以一起访问某些东西。

密码短语生成 有一些非常有创意和有趣的方法可以轻松记住超级安全的密码短语,而不是投资一些可能会危及密码安全的去中心化方法,他们应该花 2-3 分钟来获得一个他们可以记住且安全的密码与密码管理器一致使用。

一些方法包括:XKCD方法。依次使用几个与创建密码无关的单词。我认为这种方法比简单的单词需要稍微加扰,因为如果这成为常用方法,那么您可以使用常用单词轻松推导出密码破解算法,从而使其不那么令人惊奇。

密码短语/密码管理器方法在哪里使用令人难忘的短语来帮助您记住派生密码。对于长而强的密码来说,这可能是一个很好的方法。

或者,也很棒,您开发的一些尚未被提及的方法创建了一个强大的、长的、易于记忆/难以猜测的密码短语。

但我仍然要说密码/密钥恢复,例如将您的密码/密钥以纯文本形式放在其他地方供任何人查找是一个坏主意。它扩大了您的信任网络,并降低了您的整体安全性。在有人找到闯入我们思想的方法之前,我会建议我们的头脑是任何钥匙最安全的地方,而且永远都是。

如果你有一些超级重要的加密文件,你想在你死后传递给家人。将 USB 上的密钥交给他们,然后通过 USB 将文件传递给律师。像这样的情况是我真正能想到的,什么时候可能需要这样做。即便如此,还有其他一些选择。

希望这可以帮助!

密码和密钥是两个不同的项目。例如,当我们雇用新员工并且他们需要访问基于 Unix 的系统时,我们会为他们部署 ssh 密钥,这样就不会涉及密码。如果/当他们离开时,我们会撤销密钥。管理他们拥有的任何密码的需要是一个有争议的问题,因为我们可以重置密码。

考虑到有更安全的方法来传递新密码:通过电话、短信、传真,拆分密码是一种带宽浪费。

有用于企业的开源密码管理系统,例如Team Pass,做得很好,但您必须记住,允许某人创建密码的目的是为了他们并且只有他们才能进行身份验证,而不是让管理员拥有用户公开他们的密码。大多数(如果不是全部)操作系统都允许使用严格的密码。这变成了教育用户如何创建强密码的问题,否则用户会做一些事情,比如将密码贴在便利贴上等。

现在,将“密钥”和密码分开Strongkey是一个企业密钥管理系统。想象一个每个人都需要创建 GPG/PGP 密钥的企业。管理这些将是一场噩梦,因为人们可能会忘记他们的密码,用户被解雇/离开,现在没有人可以解密他/她的文件。即使可以互换使用,术语密钥和密码也不相同。