4.5 高档密钥和地址

在以下部分中,咱们将看到高档方式的密钥和地址,诸如加密私钥、脚本和多重签名地址,靓号地址,和纸钱包。

4.5.1 加密私钥(BIP0038)

私钥有必要保密。私钥的机密性需求现实情况是,在实践中相当难以完成,由于该需求与相同重要的安全方针可用性相互对立。当你需求为了防止私钥丢掉而存储备份时,会发现维护私钥私密性是一件相当困难的事情。经过暗码加密内有私钥的钱包或许要安全一点,但那个钱包也需求备份。有时,例如用户由于要晋级或重装钱包软件,而需求把密钥从一个钱包转移到另一个。私钥备份也或许需求存储在纸张上(拜见“4.5.4 纸钱包”一节)或许外部存储介质里,比方U盘。但假如一旦备份文件失窃或丢掉呢?这些对立的安全方针推进了便携、方便、能够被很多不同钱包和比特币客户端了解的加密私钥规范BIP0038的出台。

BIP0038提出了一个通用规范,运用一个口令加密私钥并运用Base58Check对加密的私钥进行编码,这样加密的私钥就能够安全地保存在备份介质里,安全地在钱包间传输,坚持密钥在任何或许被暴露情况下的安全性。这个加密规范运用了AES,这个规范由NIST树立,并广泛应用于商业和军事应用的数据加密。

BIP0038加密计划是:输入一个比特币私钥,一般运用WIF编码过,base58chek字符串的前缀“5”。此外BIP0038加密计划需求一个长暗码作为口令,一般由多个单词或一段杂乱的数字字母字符串组成。BIP0038加密计划的成果是一个由base58check编码过的加密私钥,前缀为6P。假如你看到一个6P最初的的密钥,这就意味着该密钥是被加密过,并需求一个口令来转化(解码)该密钥回到可被用在任何钱包WIT格式的私钥(前缀为5)。许多钱包APP现在能够辨认BIP0038加密过的私钥,会要求用户供给口令解码并导入密钥。第三方APP,诸如十分好用根据浏览器的Bit Address,能够被用来解码BIP00038的密钥。

最一般运用BIP0038加密的密钥用例是纸钱包——一张纸张上备份私钥。只需用户挑选了强口令,运用BIP0038加密的私钥纸钱包就无比的安全,是一种很棒的线下比特币存储途径(也被称作“冷库”)。

在bitaddress.org上测试表4-10中加密密钥,看看你怎么得到输入口令的加密密钥。

表4-10 BIP0038加密私钥比如

私钥(WIF) 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn
暗码 MyTestPassphrase
加密私钥(BIP0038) 6PRTHL6mWa48xSopbU1cKrVjpKbBZxcLRRCdctLJ3z5yxE87MobKoXdTsJ

4.5.2 P2SH (Pay-to-Script Hash)和多重签名地址

正如咱们所知,传统的比特币地址从数字1最初,来源于公钥,而公钥来源于私钥。尽管任何人都能够将比特币发送到一个1最初的地址,但比特币只能在经过相应的私钥签名和公钥哈希值后才干消费。

以数字3最初的比特币地址是P2SH地址,有时被错误的称谓多重签名或多重签名地址。他们指定比特币买卖中受益人作为哈希的脚本,而不是公钥的所有者。这个特性在2012年1月由BIP0016引进,现在由于BIP0016供给了添加功用到地址自身的时机而被广泛的采纳。不同于发送资金到传统1最初的比特币地址的买卖,也被称为P2PKH,资金被发送到3最初的地址时,不仅仅需求一个公钥的哈希值,一起也需求一个私钥签名作为所有者证明。在创立地址的时候,这些要求会被界说在脚本中,所有对地址的输入都会被这些要求隔绝。

一个P2SH地址从事务脚本中创立,它界说谁能消耗这个事务输出。(132页“P2SH(Pay-to-Script-Hash)”一节对此有详细的介绍)编码一个P2SH地址触及运用一个在创立比特币地址用到过的双重哈希函数,而且只能应用在脚本而不是公钥:

script hash = RIPEMD160(SHA256(script))

脚本哈希的成果是由Base58Check编码前缀为5的版本、编码后得到最初为3的编码地址。一个P2SH地址比如是32M8ednmuyZ2zVbes4puqe44NZumgG92sM。

P2SH 不一定是多重签名的买卖。尽管P2SH地址一般都是代表多重签名,但也或许是其他类型的买卖脚本。

4.5.2.1 多重签名地址和P2SH

现在,P2SH函数最常见的完成是用于多重签名地址脚本。望文生义,底层脚本需求多个签名来证明所有权,尔后才干消费资金。规划比特币多重签名特性是需求从总共N个密钥中需求M个签名(也被称为“阈值”),被称为M-的-N的多签名,其间M是等于或小于N。例如,第一章中提到的咖啡店主鲍勃运用多重签名地址需求1-2签名,一个是属于他的密钥和一个属于他伙伴的密钥,以保证其间一方能够签署度过一个事务锁定输出到这个地址。这类似于传统的银行中的一个“联合账户”,其间任何一方爱人能够凭借单一签名消费。或Gopesh, Bob雇佣的网页规划师创立一个网站,或许为他的事务需求一个2-3的多签名地址,保证没有资金会被花费除非至少两个事务合作伙伴签署这笔买卖。

咱们将会在第五章节探索怎么运用P2SH地址创立事务用来消费资金。

4.5.3 比特币靓号地址

靓号地址包括了可读信息的有用比特币地址。例如,1LoveBPzzD72PUXLzCkYAtGFYmK5vYNR33便是包括了Base-58字母love的。靓号地址需求生成并经过数十亿的候选私钥测试,直到一个私钥能生成具有所需图画的比特币地址。尽管有一些优化过的靓号生成算法,该方法有必要触及随机上挑选一个私钥,生成公钥,再生成比特币地址,并查看是否与所要的靓号图画相匹配,重复数十亿次,直到找到一个匹配。

一旦找到一个匹配所要图画的靓号地址,来自这个靓号地址的私钥能够和其他地址相同的方式被具有者消费比特币。靓号地址不比其他地址具有更多安全性。它们依靠和其他地址相同的ECC和SHA。你无法比任何别的地址更容易的获得一个靓号图画最初的私钥。

在第一章中,咱们介绍了Eugenia,一位在菲律宾作业的儿童慈悲总监。咱们假定Eugenia组织了一场比特币募捐活动,并期望运用靓号比特币地址来宣告这个募捐活动。Eugenia将会创造一个以1Kids最初的靓号地址来促进儿童慈悲募捐的活动。让咱们看看这个靓号地址怎么被创立,这个靓号地址对Eugenia慈悲募捐的安全性又意味着什么。

4.5.3.1 生成靓号地址

咱们有必要认识到运用来自Base58字母表中简略符号来代表比特币地址是十分重要的。查找“1kids”最初的图画咱们会发现从1Kids11111111111111111111111111111到1Kidszzzzzzzzzzzzzzzzzzzzzzzzzzzzz的地址。这些以“1kid”最初的地址规模中大约有58的29次方地址。表4-11显示了这些有“1kids”前缀的地址。

表4-11 “1Kids”靓号的规模

From 1Kids11111111111111111111111111111
To 1Kidszzzzzzzzzzzzzzzzzzzzzzzzzzzzz

咱们把“1Kids”这个前缀当作数字,咱们能够看看比特币地址中这个前缀呈现的频率。假如是一台一般功用的桌面电脑,没有任何特别的硬件,能够每秒发现大约10万个密钥。

表4-12 靓号的呈现的频率(1KidsCharity)以及生成所需时刻

长度 地址前缀 概率 平均生成时刻
1 1K 1/58 < 1毫秒
2 1Ki 1/3,364 50毫秒
3 1Kid 1/(195*103) < 2秒
4 1Kids 1/(11*106) 1分钟
5 1KidsC 1/(656*106) 1小时
6 1KidsCh 1/(38*109) 2天
7 1KidsCha 1/(2.2*1012) 3–4 月
8 1KidsChar 1/(128*1012) 13–18年
9 1KidsChari 1/(7*1015) 800年
10 1KidsCharit 1/(400*1015) 46,000年
11 1KidsCharity 1/(23*1018) 250万年

正如你所见,Eugenia将不会很快地创立出以“1KidsCharity”最初的靓号地址,即便她有数千台的电脑一起进行运算。每添加一个字符就会添加58倍的核算难度。超越七个字符的查找方式一般需求专用的硬件才干被找出,比如用户定制的具有多图形处理单元(GPU)的桌面级设备。那些一般是无法继续在比特币挖矿中盈利的钻机,被从头赋予了寻觅靓号地址的任务。用GPU体系查找靓号的速度比用通用CPU要快很多个量级。

另一种寻觅靓号地址的方法是将作业外包给一个矿池里的靓号矿工们,如靓号矿池中的矿池。一个矿池是一种允许那些GPU硬件经过为别人寻觅靓号地址来获得比特币的服务。对小额的账单,Eugenia能够外包查找方式为7个字符靓号地址寻觅作业,在几个小时内就能够得到成果,而不用用一个CPU查找上几个月才得到成果。

生成一个靓号地址是一项经过蛮力的进程:测验一个随机密钥,查看成果地址是否和所需的图画想匹配,重复这个进程直到成功找到停止。例4-8是个靓号矿工的比如,用C++程序来寻觅靓号地址。这个比如运用到了咱们在56页“其他代替客户端、资料库、东西包”一节介绍过的libbitcoin库。

例4-8 靓号挖掘程序

#include // The string we are searching forconst std::string search = "1kid";// Generate a random secret key. A random 32 bytes.bc::ec_secret random_secret(std::default_random_engine& engine); // Extract the Bitcoin address from an EC secret.std::string bitcoin_address(const bc::ec_secret& secret);// Case insensitive comparison with the search string.bool match_found(const std::string& address);int main() https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg    std::random_device random;     std::default_random_engine engine(random());     // Loop continuously...    while (true)     https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg        // Generate a random secret.        bc::ec_secret secret = random_secret(engine);         // Get the address.        std::string address = bitcoin_address(secret);         // Does it match our search string? (1kid)        if (match_found(address))         https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg            // Success!            std::cout << "Found vanity address! " << address << std::endl;             std::cout << "Secret: " << bc::encode_hex(secret) << std::endl; return 0;        }     }    // Should never reach here!    return 0; }bc::ec_secret random_secret(std::default_random_engine& engine)https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg    // Create new secret...    bc::ec_secret secret;    // Iterate through every byte setting a random value... for (uint8_t& byte: secret)        byte = engine() % std::numeric_limits::max();     // Return result.    return secret;}std::string bitcoin_address(const bc::ec_secret& secret) https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg    // Convert secret to pubkey...    bc::ec_point pubkey = bc::secret_to_public_key(secret);     // Finally create address.    bc::payment_address payaddr; bc::set_public_key(payaddr, pubkey);    // Return encoded form.    return payaddr.encoded(); }bool match_found(const std::string& address) https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg    auto addr_it = address.begin();    // Loop through the search string comparing it to the lower case     // character of the supplied address.    for (auto it = search.begin(); it != search.end(); ++it, ++addr_it)        if (*it != std::tolower(*addr_it))             return false;    // Reached end of search string, so address matches.    return true;     }

示例程序需求用C编译器链接libbitcoin库(此库需求提前装入该体系)进行编译。直接履行vanity-miner的可履行文件(不用参数,拜见例4-9),它就会测验磕碰以“1kid”最初的比特币地址。

例4-9 编译并运转vanity-miner程序示例

$ # Compile the code with g++$ g++ -o vanity-miner vanity-miner.cpp $(pkg-config --cflags --libs libbitcoin) $ # Run the example$ ./vanity-minerFound vanity address! 1KiDzkG4MxmovZryZRj8tK81oQRhbZ46YTSecret: 57cc268a05f83a23ac9d930bc8565bac4e277055f4794cbd1a39e5e71c038f3f$ # Run it again for a different result$ ./vanity-minerFound vanity address! 1Kidxr3wsmMzzouwXibKfwTYs5Pau8TUFnSecret: 7f65bbbbe6d8caae74a0c6a0d2d7b5c6663d71b60337299a1a2cf34c04b2a623# Use "time" to see how long it takes to find a result$ time ./vanity-minerFound vanity address! 1KidPWhKgGRQWD5PP5TAnGfDyfWp5yceXMSecret: 2a802e7a53d8aa237cd059377b616d2bfcfa4b0140bc85fa008f2d3d4b225349real    0m8.868suser    0m8.828ssys     0m0.035s

正如咱们运转Unix命令time所测出的运转时刻所示,示例代码要花几秒钟来找出匹配“kid”三个字符模板的成果。读者们能够在源代码中改动search这一查找模板,看一看假如是四个字符或许五个字符的查找模板需求花多久时刻!

4.5.3.2 靓号地址安全性

靓号地址既能够添加、也能够削弱安全措施,它们着实是一把双刃剑。用于改善安全性时,一个共同的地址使对手难以运用他们自己的地址代替你的地址,以诈骗你的顾客支付他们的账单。不幸的是,靓号地址也或许使得任何人都能创立一个类似于随机地址的地址,甚至另一个靓号地址,然后诈骗你的客户。

Eugenia能够让捐款人捐款到她宣告的一个随机生成地址(例如:1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy)。或许她能够生成一个以“1Kids”最初的靓号地址以显得更共同。

在这两种情况下,运用单一固定地址(而不是每比捐款用一个独立的动态地址)的风险之一是小偷有或许会黑进你的网站,用他自己的网址取代你的网址,然后将捐献转移给自己。假如你在不同的地方公布了你的捐款地址,你的用户能够在付款之前直观地查看以保证这个地址跟在你的网站、邮件和传单上看到的地址是同一个。在随机地址1j7mdg5rbqyuhenydx39wvwk7fslpeoxzy的情况下,一般用户或许会只查看头几个字符“1j7mdg”,就认为地址匹配。运用靓号地址生成器,那些想经过替换类似地址来偷盗的人能够快速生成与前几个字符相匹配的地址,如表4-13所示。

表4-13 生成匹配某随机地址的多个靓号

原版随机地址 1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy
4位字符匹配 1J7md1QqU4LpctBetHS2ZoyLV5d6dShhEy
5位字符匹配 1J7mdgYqyNd4ya3UEcq31Q7sqRMXw2XZ6n
6位字符匹配 1J7mdg5WxGENmwyJP9xuGhG5KRzu99BBCX

那靓号地址会不会添加安全性?假如Eugenia生成1Kids33q44erFfpeXrmDSz7zEqG2FesZEN的靓号地址,用户或许看到靓号图画的字母和一些字符在上面,例如在地址部分中注明晰1Kids33。这样就会迫使攻击者生成至少6个字母相匹配的的靓号地址(比之前多2个字符),就要花费比Eugenia多3364倍的靓号图画。本质上,Eugenia支付的尽力(或许靓号池支付的)迫使攻击者不得不生成更长的靓号图画。假如Eugenia花钱请矿池生成8个字符的靓号地址,攻击者将会被逼迫到10字符的境地,那将是个人电脑,甚至贵重自界说靓号挖掘机或靓号池也无法生成。对Eugenia来说可承当的起开销,对攻击者来说则变成了无法承当开销,特别是假如欺诈的回报不足以支付生成靓号地址所需的费用。

4.5.4 纸钱包

纸钱包是打印在纸张上的比特币私钥。有时纸钱包为了方面起见也包括对应的比特币地址,但这并非是必要的。由于地址能够从私钥中导出。纸钱包是一个十分有用简历备份或许线下比特币存储方式,也是被称为“冷钱包”。作为备份机制,一个纸钱包能够供给安全性,以防在电脑硬盘损坏、失窃或意外删去的情况下造成密钥的的丢掉。作为一个冷存储的机制,假如纸钱包密钥在线下生成并永久不在电脑体系中存储,他们在应对黑客攻击,键盘记录器,或其他在线电脑诈骗更有安全性。

纸钱包有许多不同的形状,巨细,和外观规划,但十分根本的原则是一个密钥和一个地址打印在纸张上。表4-14展现了纸钱包最根本的方式。

表4-14 比特币纸钱包的私钥和公钥的打印方式

公开地址 1424C2F4bC9JidNjjTUZCbUxv6Sa1Mt62x
私钥(WIF) 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn

经过运用东西,就能够很容易地生成纸钱包,比如运用bitaddress.org网站上的客户端Javascript生成器。这个页面包括所有必要的代码,甚至在完全失掉网络连接的情况下,也能够生成密钥和纸钱包。若要运用它,先将HTML页面保存在本地磁盘或外部U盘。从Internet网络断开,从浏览器中翻开文件。更方便的,运用一个原始操作体系启动电脑,比方一个光盘启动的Linux体系。任何在脱机情况下运用这个东西所生成的密钥,都能够经过USB线在本地打印机上打印出来,然后制作了密钥只存在纸张上而从未存储在在线体系上的纸钱包。将这些纸钱包放置在防火容器内,发送比特币到对应的比特币地址上,然后完成了一个简略但十分有用的冷存储解决计划。图4-14展现了经过bitaddress.org 生成的纸钱包。

图4-14 经过bitaddress.org 生成的一般纸钱包

这个简略的纸钱包体系的不足之处是那些被打印下来的密钥容易被偷盗。一个能够获取接近这些纸币的小偷能够只需偷走纸币或许用把纸币上密钥拍照下来,就能获得被这些密钥加密过的比特币的控制权。一个更杂乱的纸钱包存储体系运用BIP0038加密的私钥。这些私钥被打印在纸钱包上被所有者记住的口令维护起来。没有口令,这些被加密过的密钥也是毫无用处的。但它们依旧要比用口令维护的钱包级别要高,由于这些密钥从没有在线过,有必要从物理上从保险箱或许其他物理安全存储中导出。图4-15展现了经过bitaddress.org 生成的加密纸钱包。

图4-15 经过bitaddress.org 生成的加密纸钱包。暗码是“test”。

尽管你能够多次存款到纸钱包中,但是你最好一次性提款,一次性提取里边所有的资金。由于假如你提取的金额少于其间的金额的话,会生成一个找零地址。而且,你所用的电脑或许被病毒感染,那么就有或许走漏私钥。一次性提款能够减少私钥走漏的风险,假如你所需的金额比较少,那么请把余额找零到另一个纸钱包中。

纸钱包有许多规划和巨细,并有许多不同的特性。有些作为礼物送给别人,有季节性的主题,像圣诞节和新年主题。别的一些则是规划保存在银行金库或经过某种方式隐藏私钥的保险箱内,或许用不透明的刮刮贴,或许折叠和防篡改的铝箔胶粘密封。图4-16至图4-18展现了几个不同安全和备份功用的纸钱包的比如。

图4-16 经过bitcoinpaperwallet.com生成的、私钥写在折叠皮瓣上的纸钱包
图4-17 经过bitcoinpaperwallet.com 生成的、私钥被密封住的纸钱包

其他规划有密钥和地址的额外副本,类似于票根方式的能够拆开存根,让你能够存储多个副本以防火灾、洪水或其他自然灾害。

图4-18 在备份“存根”上有多个私钥副本的纸钱包

==目录==

简介
前言
第1章 介绍
第2章 比特币的原理
第3章 比特币客户端
第4章 密钥、地址、钱包
第4章 高档密钥和地址
第5章 买卖
第6章 比特币网络
第7章 区块链
第8章 挖矿与一致
第8章 区块链分叉、矿池、一致攻击
第9章 竞赛币、竞赛块链和应用程序
第10章 比特币安全

附录1 买卖脚本的操作符、常量和符号
附录2 比特币改善协议
附录3 pycoin库、ku程序和tx买卖程序
附录4 sx东西下一些的命令

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注