如果你不介意通过使用计算器来生成12个单词的助记词来确保随机性,那么这篇文章适合你。
作者:Max Skibinsky
使用离线计算器生成BIP39助记词是确保助记词的随机性和初始安全性非常高的一种方法,尤其是与默认钱包方法相比。
在选择生成助记词的方法时,你必须自问自己以下几个问题:你是否相信你使用的设备绝对没有任何恶意软件?今天安全的事物未必明天仍然安全。此外,你是否相信开发人员创建了足够随机的随机数生成器(RNG)?简单的数学错误可能导致所有生成的私钥可预测,从而容易受到暴力破解攻击。即使你两者都信任,你也不能百分之百确定。
通过使用计算器或骰子来生成助记词,你可以消除所有这些顾虑,因为它们提供了一个真正的隔离环境来生成熵。此过程为离线进行,你可以确信生成的熵没有受到破坏。计算器和骰子方法都可以使你因为自己控制的熵增而感到安心,并且完全离线生成助记词可以减少被拦截的风险。
简要总结:
使用计算器选择随机数可以有效地确保随机性。
可以通过计算器的随机功能选择数字,还可以选择一些额外的计算,如倒计时器,以使其更加随机。
确定正确的最后一个单词需要进行一些额外的步骤。
设置和清理环境,以消除生成的数字的任何痕迹,可能需要额外的步骤。
计算器如何生成随机性?
计算器可以依靠不同的机制来产生随机性,这取决于它们的设计。它们的熵源可以来自诸如开机以来的微秒数、芯片相关的热量水平或其他可变条件。计算器的随机函数可以将这些不可预测的基础数学值转化为伪随机数。
为了确保最大的不可预测性,如果将计算器用作随机数生成器,它不应该处于“开箱即用”的状态,而应该首先通过多次开关机和进行一些常规计算来将其初始化为非通用状态,然后再进行随机种子计算。
此外,引入额外的熵源是有用的,可以实现在赌场中所有电子老虎机使用的方法:他们编程一个随机数生成器不断生成数字,然后你可以自由地盲选,通过按下按钮来选择。使用可编程计算器可以轻松实现相同的效果。如果你的科学计算器不支持程序,那么你可以通过一些额外的操作手动实现相同的效果。
如何准备使用计算器生成助记词?
为了准备使用计算器进行助记词计算,请准备以下内容:
1. 一个带有随机函数的独立科学计算器。
支持随机函数的计算器型号包括惠普10S或30S、德州仪器TI-30XB或TI-83/84、卡西欧FX-991或FX-5800P,或夏普EL-W535等。
2. BIP39单词列表(英文单词列表可参考https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt)。
3. 准备好的加密货币钱包,用于初始化生成的助记词。
4. 用于按顺序写入生成的随机数字和相应单词的草稿纸。
5. 理解如何计算和验证助记词的最后一个单词。(这里有更多详细信息。)
6. 在生成助记词后备份助记词的策略和设备。(例如,可以将助记词存储在加密钱包中,并将其打孔在钢卡上。)
7. 对于生成和备份助记词后,如何处理草稿纸的计划。(例如,草稿纸和底下几页可能有压痕的纸张可以放在防火容器中燃烧。)
计算器的随机函数是什么?
大多数计算器允许用户设置整数范围进行随机化,该范围包括起始和结束数字(例如,从1到2048)。在特定计算器上调用随机函数的确切按键将在用户手册中定义,但该函数通常使用标有“Rand”的按钮,或使用Shift-Rand或2nd-Function-Rand组合按键调用。
在可编程计算器上,使用randInt(A, B)函数进行调用,其中A和B是包含的起始和结束数字。通过将随机范围设置为1-3来测试随机函数的操作,并检查几次运行的结果,确认指定的初始和结束数字是否包含在结果集中。然后将随机范围设置为1-2048,以便将结果映射到BIP39单词列表。
使用计算器生成助记词的高级视图是什么?
大多数助记词的生成是直接的:使用计算器的随机函数,执行并将数字及其对应的BIP39单词按照生成的顺序写入纸上,重复此过程,直到生成了12个数字和单词。
助记词的最后一个单词需要额外的分析和调整,因为BIP39标准要求为了保证短语的完整性,最后一个单词必须包含从前11个单词派生出的有效校验和。在单词列表的每个16个单词块中,只有一个单词包含了对前11个选择的单词的有效校验和。
下面的步骤描述了如何生成单词以及如何确定正确的最后一个单词。以下,我们展示了两种方法,分别适用于可编程和非可编程计算器。
如何使用非编程计算器生成随机的助记词?
如果你使用的是非可编程计算器,那么大部分助记词的生成是直接的。
1. 使用计算器的随机函数,将其设置在范围(111111,999999)内执行多次,直到你得到一些没有任何零的数字。选择其中两个数字,并将其数字作为在步骤4中的随机倒计时计时器的12个不同秒值。
2. 然后设置一个手机计时器(不是倒计时),开始计时,并将其放在你前面以方便使用。
3. 将计算器的随机函数设置在范围(1,2048)内执行。
4. 一直按下[enter]键,连续执行相同的随机函数,持续X秒,其中X是在步骤1中生成的第一个六位随机数的第一个数字。计时的精确度不会影响结果,这些步骤引入了外部的随机因素,就像我们在掷骰子之前摇动一样。
5. 完成后,按照生成的顺序将数字和相应的BIP39单词写入纸上。
6. 重复步骤4和5,直到生成了12个数字和单词。
助记词的最后一个单词需要额外的分析和调整,因为BIP39标准要求为了保证短语的完整性,最后一个单词必须包含从前11个单词派生出的有效校验和。在单词列表的每个16个单词块中,只有一个单词包含了对前11个选择的单词的有效校验和。详见“确定最后一个单词”的步骤。
如何使用可编程计算器生成随机的助记词?
如果你有一个可编程计算器,那么你可以按照更自动化的方法进行操作:
下面提供的示例适用于TI-83/84计算器。
创建一个程序,按照以下按钮进行导航:
[prgm] -> New -> 1: Create New -> name=RANDOM -> [enter]
然后将以下代码放入编辑器中:
PROGRAM:RANDOM
:While 1
:randInt(1,2048)→R
:If getKey>0
:Disp R
:End
在程序编辑器中,可以通过 [prgm] -> CTL 文件夹访问 While、If、End 操作。
在程序编辑器中,可以通过 [math] -> PROB 文件夹访问 randInt 操作。
在程序编辑器中,可以通过 [sto→] 访问→操作。
在程序编辑器中,可以通过 [prgm] -> I/O 文件夹访问 getKey、Disp 操作。
在程序编辑器中,可以通过 [2nd] -> [math] -> TEST 文件夹访问 > 操作。
完成代码后,可以通过导航到 [alpha] -> [graph] -> [f5] -> 1: Execute Program -> [ENTER] 启动程序。
按下除 ON 键以外的任意键,即可获取生成的下一个数字。你可以通过多次测试生成来热身生成器,并检查它是否正确工作,是否在1到2048的范围内显示随机数。
现在你已经准备好开始生成助记词了:再次按下任意键,在生成的顺序上将数字和相应的BIP39单词写入纸上,重复此过程,直到生成了12个数字和单词。
当你按下 [ON] -> [ENTER] 时,程序被中断并停止运行。
助记词的最后一个单词需要额外的分析和调整,因为BIP39标准要求为了保证短语的完整性,最后一个单词必须包含从前11个单词派生出的有效校验和。在单词列表的每个16个单词块中,只有一个单词包含了对前11个选择的单词的有效校验和。请继续进行下一步:确定最后一个单词。
备注:
该程序一直在运行,每秒生成大约30个数字,使用randInt(1,2048)。显示的数字取决于按键的时刻。
这种方法在所有赌场的电子老虎机中都在使用。它们的伪随机数生成器每秒生成大约500个数字,这是因为所选数字的范围远小于2048。
确定最后一个单词。
有两种方法可以确定有效的最后一个单词:
在没有连接到互联网且处于安全的操作环境中,在浏览器的代码调试窗口中运行本文末尾提供的脚本。在运行脚本之前,修改包含名为"data"的数组的脚本行,使其包含你使用计算器随机选择的十二个整数。例如,以下脚本中的行表示你在计算器上计算了以下十二个数字:
data = [101, 502, 962, 1400, 1607, 1817, 1090, 1827, 820, 1334, 156, 1073]
它们对应以下单词:
arrive dirt join puzzle silver toast market tone grid pluck beach maid
在Firefox浏览器中运行脚本,打开Web控制台(快捷键:Control-Shift-K),在提示符下粘贴整个脚本,然后按Enter。脚本运行后,它应该显示从那个16个单词块中应该选择的有效的第十二个单词种子数(而不是你使用计算器生成的数字)。脚本的输出应该类似于以下内容:
function checksum12words(data) {
if (data.length != 12) return console.log("ERROR: Need 12 words numbers as input");
let binder = (s, l = 8) => s.toString(2).padStart(l, "0");
let tone = (bytes) => bytes.map(x => x.toString(16).padStart(2, 0)).join(" ");
let bytes = data.map(x => binder(x - 1, 11)); //convert 0-index to binary
Entropy is: 0c87d5e0d77c8dc6220f226674d44dc3
"OK"
Your 12th word index is: 1078
这个脚本的输出将显示你的助记词的第十二个数字,经过调整以获得有效的校验和,应该是1078,而不是最初使用计算器选择的1073。相应地,BIP39单词列表显示你的助记词的有效的最后一个单词应该不是"maid",而是"mammal"。
第二种确定有效的最后一个助记词单词的方法可以替代或与第一种方法一起使用。它包括使用离线助记词转换工具。这涉及将原始的12个助记词单词输入转换工具中,然后通过试错的方式确定包含最初选择的第十二个单词的16个单词块中哪个单词相对于短语具有有效的校验和。例如,如果计算的第十二个单词数字是1073,首先确定包含数字1073的单词块是哪个:在1-2048个单词的BIP39单词列表中,第68个16个单词块包含单词1073-1088。因此,包含单词1073的单词块是1073-1088。
备注:有些人在打印的单词列表中突出显示每16个单词的单词,以便更容易识别单词块。
现在,我们知道有效的第十二个单词在单词列表的1073-1088范围内,将由计算器选择生成的原始单词集粘贴到助记词代码转换工具的“BIP39助记词”字段中:
arrive dirt join puzzle silver toast market tone grid pluck beach maid
该工具将自动计算并显示错误消息"Invalid mnemonic",因为它使用最后一个单词"maid"计算时没有产生有效的校验和。
现在开始进行试错测试,将助记词短语中的最后一个单词从"maid"(单词1073)更改为"mail"(1074),"main"(1075),"major"(1076)和"make"(1077)。每次,工具都会再次显示"Invalid mnemonic"错误。但是当我们将最后一个单词更改为"mammal"(1078)时,错误消失,转换工具认可它。(这个结果与上述方法1中的结果一致)。助记词已经成功生成!
除了你现在有效的BIP39助记词外,转换工具输出还显示了其他各种信息,如地址、二维码、适用于BIP44钱包的扩展密钥等。然而,你将要将助记词输入到自己的钱包中,一旦你这样做,你应该依靠自己的钱包来获取其他信息(它将根据助记词生成)。
如何在生成助记词后清理浏览器数据?
在安全存储助记词信息之后,应清除浏览器缓存并退出浏览器进程,以从浏览器和计算机内存中删除所有敏感数据的痕迹。
如果你使用了临时操作环境,比如Tails Linux,那么清除浏览器内存并不是必需的,因为整个操作环境的数据都不会写入磁盘,并且在停止实例时会从内存中删除所有数据。
如果你在离线的非临时操作系统中使用了浏览器,应查阅所使用的特定浏览器版本的文档,确保完成清除缓存和历史记录的所有步骤,包括已呈现窗口和运行脚本的控制台。
对于Chrome浏览器,可能包括选择菜单项"更多工具","清除浏览数据","全部时间",并额外选择"Cookie和网站数据","缓存的图像和文件",然后点击"清除数据"。
要在Chrome中清除控制台历史记录,控制台窗口提供了一个上下文菜单"清除控制台历史记录"。
对于Firefox浏览器,可能包括选择菜单项"隐私与安全","Cookie和网站数据",勾选所有可用框,然后点击"清除"按钮。
要在Firefox中清除控制台历史记录,请运行"clearhistory()"命令。
安全提示:在浏览器中非常小心使用助记词
本文提供了一种使用离线计算器作为随机源生成12个助记词(也称为"助记短语")的方法论。然而,一些后续步骤涉及在计算机浏览器中运行脚本。助记词应该只在安全环境下生成,以尽量减小被拦截、篡改或盗窃的风险。助记词绝不能通过任何网络传输,也不能存储在任何计算机上,除非进行加密保护。
为了确保在浏览器中进行助记词生成步骤时的安全操作环境,一个好的选择是使用一个离线的临时操作系统,比如Tails Linux中的浏览器。在将浏览器中生成的助记词复制到长期安全存储中时,不要通过将它们复制粘贴到中间存储设备上的文件中留下电子痕迹...准备好你的钱包,在生成助记词时就将其输入到钱包中。
以下是校验和脚本的代码:
javascript
Copy code
function checksum12words(data) {
if (data.length != 12) return console.log("ERROR: Need 12 words numbers as input");
let binstr = (s, l = 8) => s.toString(2).padStart(l, '0');
let tohex = (bytes) => bytes.map(x => x.toString(16).padStart(2, 0)).join('');
let bytes = data.map(x => binstr(x - 1, 11)) // convert 0-index to binary
.join('').match(/.{1,8}/g) // split 8 bits
.map(x => parseInt(x, 2)); // convert to UInt8
if (bytes.length != 17) return console.log("ERROR: Something is wrong, check your input");
bytes.pop(); // remove wrong 17th byte of checksum
console.log("Entropy is: ", tohex(bytes));
window.crypto.subtle.digest("SHA-256", new Uint8Array(bytes).buffer).then(x => {
if (x.byteLength != 32) return console.log("ERROR: Wrong SHA256");
let hash = new Uint8Array(x);
let cs = binstr(hash[0]).match(/.{1,4}/g)[0]; // That's our checksum
// Take byte 15 for full 11 bits of our final word
let bits = [binstr(bytes[15]), cs].join('');
if (bits.length != 12) return console.log("ERROR: Wrong final word bits");
console.log("Your 12th word index is: " + (1 + parseInt(bits.substr(1), 2)));
});
return "OK";
}
data = [101, 502, 962, 1400, 1607, 1817, 1090, 1827, 820, 1334, 156, 1073];
checksum12words(data);
请将上述代码复制到代码编辑器中运行,确保数据数组 data 包含了你生成的十二个随机数字。运行脚本后,将会输出校验和的相关信息,包括熵值和助记词的第十二个单词索引。
所有评论