IOT硬件与区块链硬件安全
评测与深度资讯聚集地

比特币交易技术连载:比特币原始数据前世今生

最近有不少朋友想让我介绍一下区块链底层算法的东西,刚好本人近期也跟一些大牛讨论,略有一点心得,今天整理一下,跟大家一起探讨。

大家可能对比特币挖矿有初步了解,然而,却有很少人关注挖矿之前,比特币究竟干了些什么,那么今天,我就比特币原生数据的来龙去脉给大家抛砖引玉。

所谓交易原生数据,讲得通俗一点,其实就是点对点广播出去的数据,这些数据被节点接收,然后验证。一般情况下,交易原生数据被钱包签名并广播后,用户只需要确认转账地址跟转账金额。

手动广播比特币原始数据可以通过:https://live.blockcypher.com/btc/pushtx/(测试网数据广播)。(注意,本文所列举数据均为比特币测试网环境下所得)

在得到交易原生数据之前,我们得先讲一讲公私钥对。众所周知(当然也有部分读者不知道 ^_^),比特币的核心是椭圆曲线算法,确切地说,是椭圆曲线算法里面的secp256k曲线,这是个什么东西呢?不懂的读者可以简单理解为,椭圆曲线有很多参数,不同的参数可以构建不同的曲线,而这个secp256k就是构成比特币核心算法的参数。具体的曲线图,我就不贴了,随便百度。

好,曲线确定下来了,接下来就是确定公私钥对,确切一点讲,是确定私钥,毕竟公钥可以通过私钥计算出来,至于怎么由私钥推导公钥,由于篇幅跟主题所限,后续有时间我再单独开个专题详细讲解,这里就不偏题了。

私钥,其实就是一串32字节/256bit的随机数,但是,产生这个随机数的时候,一定要保证这个随机数的随机性,这涉及到密码学里面的一个真随机和伪随机的概念,这里也不做延申。

私钥就是你的命根子,可以这样描述私钥在整个比特币系统中的地位,失去了私钥,也就等于失去了你的比特币,因此,任何有关比特币的文章,我们都可以看到对私钥重要性的强调。(这就是为何钱包的安全性非常重要的原因)

既然私钥这么重要,那么我们肯定要好好保存,问题是,这么一堆没有任何规律的随机数,说不定我哪天就忘记了,怎么办呢?别担心,比特币大牛已经帮我们想好了偷懒的方式,那就是贯穿整个比特币系统的3大协议(我个人理解的3大协议,哈哈):BIP32,BIP39,BIP44。

这3个协议可以在github上找到:

https://github.com/bitcoin/bips

具体这3个协议用来干吗呢?我整理了一下,读者朋友可以先有个简单的概念:

BIT39:用一系列词组(可以是12/15/18/24个单词或者汉字或者其他语言)来代表根种子,最终的主私钥可以通过这个根种子计算得出。

BIT32: 主要用在分层确定性钱包体系,通俗点讲,就是将主私钥通过一定规则,分散出很多个(可以理解为无限多个)私钥,每个私钥都可以用来做有效签名。

BIP44: 它基于BIP32,可以理解为用来区分不同的币种。

言归正传,假设我们现在得到了一个32字节的随机数(e45a9445e5713b616dc0badb01534815622eeb50f7816bfcc927b90b37d4ede8eab3b49b06c08f2623a66ab1990c4ece9f542b51bd94e0a2e151bf0bc192ae90),我们想把它作为我们的根种子,要想通过BIP39协议得到一个便于用户识别的助记词词组,需要执行如下步骤:

  1. 确认用户最终想得到的助记词词组使用的语言,一般是英文,当然也包括简体中文,繁体中文,法文,日文等等,这些助记词的词库可以在github上找到,每个单词都是经过千挑万选,可以最大限度降低用户输入时的错误。
  2. 假设此处我们使用英文的助记词,然后,需要使用一个简单的算法,将32字节私钥转换成一系列助记词,算法我用C语言描述如下:

//bits:输入数据

//len = 32

const char *getData_from_wordList(const uint8_t *data, int len)

{

if (len % 4 || len < 16 || len > 32) {

return 0;

}

uint8_t bits[32 + 1];

 

sha256_Raw(data, len, bits);

// checksum

bits[len] = bits[0];

// data

memcpy(bits, data, len);

 

int mlen = len * 3 / 4;

static char mnemo[24 * 10];

int i, j, idx;

char *p = mnemo;

for (i = 0; i < mlen; i++) {

idx = 0;

for (j = 0; j < 11; j++) {

idx <<= 1;

idx += (bits[(i * 11 + j) / 8] & (1 << (7 – ((i * 11 + j) % 8)))) > 0;

}

strcpy(p, wordlist[idx]);

p += strlen(wordlist[idx]);

*p = (i < mlen – 1) ? ‘ ‘ : 0;

p++;

}

return mnemo;

}

  1. 我们使用这个接口得到了一个12字节的助记词:chronic demise crawl help alert outdoor tunnel ticket art tonight food mistake

 

OK,助记词搞定,用户只需要记住这12个单词,那么在任何支持BIP39/BIP32协议的钱包上,都可以用这12个单词来恢复自己的账户,即使你的钱包被删除,只要这12个单词没有丢,那么就不用担心账户里的比特币丢失,相比于一串无规律的数字,这12个单词是不是显得更可爱呢?

我把助记词理解为比特币的前世,那么,根据比特币前世的12个小机灵鬼(此处12个只是示例,它也有可能是15个,18个,24个),我们就可以顺藤摸瓜,开始我们比特币帝国的探索之路了。

首先,我在:https://www.electrum.org/#home 上下载了一个软钱包,然后填入我们的助记词,为了避免有读者以为我们这是一篇electrum的使用说明文档,electrum钱包的具体安装过程就不多做赘述了,见下图吧。

细心的读者已经发现了,点开electrum钱包的“Addresses”选项之后,出现了很多数据,这些数据是什么东西?作用是什么呢?

其实,这些数据就是所谓的转账地址,别人如果需要给我转账,我就可以随便选一组数据给他,然后通过这个地址,他就可以把比特币转给我了,至于为何会有这么多地址,这就是我前文所述,BIP32和BIP44协议可以分散出无限多个地址。

我们来对这些地址进行说道说道。

已知我们现在只有一个根种子:e45a9445e5713b616dc0badb01534815622eeb50f7816bfcc927b90b37d4ede8eab3b49b06c08f2623a66ab1990c4ece9f542b51bd94e0a2e151bf0bc192ae90,第一步,我们应该先把他转换成私钥,转换的过程很多文章写得比较复杂,我简单写了个python脚本实现:

import hashlib

import string

import binascii

Seed = ‘e45a9445e5713b616dc0badb01534815622eeb50f7816bfcc927b90b37d4ede8eab3b49b06c08f2623a66ab1990c4ece9f542b51bd94e0a2e151bf0bc192ae90’

Passphase = ‘426974636F696E2073656564’

 

def hex_string_to_list(hex_string):

# convert hex string to byte list

byte_list = []

for i in range(len(hex_string) / 2):

hex_byte_string = hex_string[i*2:i*2+2]

b = binascii.unhexlify(hex_byte_string)

byte_list.append(ord(b))

return byte_list

 

def hmac_sha512(key_str=None, msg_str=None):

key = hex_string_to_list(key_str)

buf = [0]*128

buf_str = ”

o_key_pad = [0]*128

o_key_pad_str = ”

i_key_pad = [0]*128

i_key_pad_str = ”

 

if len(key) > 128:

buf_str += (hashlib.sha512(h2b(key_str)).hexdigest())

buf[0:64] = hex_string_to_list(buf_str)

else:

buf[0:len(key)] = key

 

for i in range(128):

o_key_pad[i] = buf[i] ^ 0x5c

i_key_pad[i] = buf[i] ^ 0x36

 

o_key_pad_str += list_to_hex_string(o_key_pad)

i_key_pad_str += list_to_hex_string(i_key_pad)

 

tmp_str = hashlib.sha512(h2b(i_key_pad_str+msg_str)).hexdigest()

msg_str = hashlib.sha512(h2b(o_key_pad_str+tmp_str)).hexdigest()

return msg_str

 

privKey = hmac_sha512(Passphase, seed)

 

这个privKey就是我们的终极主私钥,一切地址的祖宗,@_@。此处得出的结果是:55a35d6e44b0e7f58c10f18c6e0112b10b581b87473b4fb6038e6372a8a73099e682d18565586cf0b55ff30f75a7c7a79802803e3edd4246c7893bc7e622aeb3

然后,我们就遇到了探索路上的第一个BOSS,BIP32/BIP44。这两个协议可以说是整个比特币帝国的支柱,为什么呢?。。。。。。因为拥有了他们,你的账户就像学会了影分身,瞬间可以得到无数个你。

今天先写到这里,后续BIP32跟BIP44讲解,将会在近期更新。

赞(0) 打赏
未经允许不得转载:硬件钱包评测-区块链-冷比特 » 比特币交易技术连载:比特币原始数据前世今生
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

硬件级安全

MODSEMI联系我们