我在您最初的问题下写了一些评论,但我觉得将我的评论(描述解决方案)与迄今为止提到的所有答案结合起来可能会产生您可以实际使用的东西(而不是自己研究)。
正如评论中提到的,拆分密钥技术是制作 X 个子密钥的过程。最常见的实现方式是要求所有 X 子密钥来恢复受保护的密钥。
在我接下来讨论的示例中,我将定义以下单词以确保清晰:
key:静态(又名共享/对称)或基于密码或密码生成的加密变量。
密码:人类通常记住的明文或其他非加密衍生值(或者,可耻的是,写在键盘下的便签上)。
passphrase:就本例而言,passphrase 与密码相同。
sub-key :与被保护的密钥大小相等的单个恢复信息块。
split-key:将恢复密钥分解为各种拆分(又名sub-key或chunks)的概念。
字典字符:用户可以输入到恢复机制中的字符集(例如,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以创建key、sub-key 1 和sub-key 2。
感谢并享受!