二. 密钥和地址
1. 比特币所有权
比特币所有权是通过数字密钥、比特币地址和数字签名来确定的
2. 数字密钥
密钥是成对出现的,由一个私钥和一个公钥所组成。一般情况下,比特币地址由一个公钥生成并对应于这个公钥。
而私钥和公钥的关系是:K = k * G (椭圆曲线乘法。其中k是私钥,G是被称为生成点的常数点,而K是所得公钥),是不可逆转过程,即私钥可以计算得出公钥,而通过公钥推算不出私钥。这种非对称加密,可以放心使比特币地址在比特币网络中传播,任何人都可以验证每笔交易的每个签名,从而实现了去中心化信任和控制。
2.1 私钥是从一个随机数中生成(二进制256位),更准确地说,私钥可以是1和n-1之间的任何数字,其中n是一个常数(n=1.158 * 10^77,略小于2^256)。可以通过使用密码学安全的伪随机数生成器(CSPRNG),和一个具有足够熵值的源的种子生成。(应该是使用SHA256哈希算法进行运算)
一个16进制私钥:
1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD
2.2 椭圆曲线乘法K = k * G:所有比特币用户的生成点(G)是相同的,G点可以用坐标(x,y)表示,而在椭圆曲线中,点的相加等同于从该点画切线找到与曲线相交的另一 点,然后翻折到x轴。公钥K就是由生成点(G)相加k次所得。
2.3 公钥生成地址如下图步骤:
从Bitbill钱包中也可看出,比特币地址相当于支付宝转账收款人,是由公钥经过单向的哈希函数生成的。
1)公钥生成地址公式:A = RIPEMD160(SHA256(K))(K 是公钥,A 是生成的比特币地址)
即双哈希得到公钥哈希,然后通过Base58Check编码生成。
2)Base58Check编码
Base58不含Base64中的0(数字0)、O(大写字母o)、l(小写字母 L)、I(大写字母i),以及“+”和“/”两个字符,这种编码格式不仅实现了数据压缩,保持了易读 性,还具有错误诊断功能。
a)对数据添加一个称作“版本字节”的前缀
b)对之前的结果(前缀和数据)运行两次SHA256哈希算法(checksum = SHA256(SHA256(prefix+data))),产生的长32个字节的哈希值(两次哈希运算)中,我们只取前4个字节作为校验和,添加入数据
c) Base58 Encode
3)Base58Check版本前缀和编码后的结果(比特币地址以1开头。。)
2.4 钥匙的格式
1)公钥的格式
有非压缩格式或压缩格式公钥这两种形式
公钥是在椭圆曲线上的一个点,由一对坐标(x,y)组成,每个公钥有520比特,一个256比特数字是公钥的x坐标,另一个256比特数字是y坐标,前缀04是用来区分非压缩格式公钥, 压缩格式公钥是以02或者03开头。(需要这两种不同前缀的原因是:因为y的解是来自于一个平方根,如果y是偶数,则使用02作为前缀;如果y是奇数,则使用03作为前缀)
如果我们知道了公钥的x坐标,就可以通过解方程y2 mod p = (x3 + 7) mod p得到y坐 标。这种方案可以让我们只存储公钥的x坐标,略去y坐标,从而将公钥的大小和存储空间减少了256比特,每个交易所 需要的字节数减少了近一半,随着时间推移,就大大节省了很多数据传输和存储。
压缩格式公钥渐渐成为了各种不同的比特币客户端的默认格式,两种格式私钥是一样的,但是公钥却可以生成两个不同的比特币地址。所以,处理那些来自较老的不支持压缩格式公钥的客户端的交易,私钥将只能被导出为WIF格式(以5为前缀)导 出;而当从一个实现了压缩格式公钥的新的比特币钱包导出私钥时,钱包导入格式(WIF)将会被修改为WIF压缩格式,该格式将会在私钥的后面附加一个字节大小的后缀01(“压缩的私钥”实际上只是表示“用于生成压缩格式公钥的私钥”)
2.5 加密私钥(BIP0038)
BIP0038加密方案是:输入一个比特币私钥,通常使用WIF编码过,base58chek字符串的前缀“5”。此外BIP0038加密方案需要一个长密码作为口令,通常由多个单词或一段复杂的数字字母字符串组成。
2.6 多重签名
以数字3开头的比特币地址是P2SH地址,有时被错误的称谓多重签名或多重签名地址。他们指定比特币交易中受益人为哈希的脚本,而不是公钥的所有者
三. 钱包
广义上,钱包是一个应用程序,为用户提供交互界面。 钱包控制用户访问权限,管理密钥和地址,跟踪余额以及创建和签名交易。 狭义上,即从程序员的角度来看,“钱包”是指用于存储和管理用户密钥的数据结构。
所以,钱包里面没有钱的,有的只是钥匙。
1)钱包类型
可分为两种类型,区别在于它们包含的多个密钥是否相互关联:
第一种类型是非确定性钱包(nondeterministic wallet),其中每个密钥都是从随机数独立生成的。密钥彼此无关。
第二种类型是确定性钱包(deterministic wallet),其中所有的密钥都是从一个主密钥派生出来,这个主密钥即为种子(seed)。该类型钱包中所有密钥都相互关联,如果有原始种子,则可以再次生成全部密钥。确定性钱包中使用了许多不同的密钥推导方法。最常用的推导方法是使用树状结构,称为分级确定性钱包或HD钱包。
HD钱包有两个主要的优势。第一,树状结构可以被用来表达额外的组织含义。不同分支的密钥都可以被用在企业环境中,这就可以支配不同的分支部门、子公司、具体功能以及会计类别。
HD钱包的第二个好处就是它可以允许让使用者去建立一个公共密钥的序列而不需要访问相对应的私钥。这可允许HD钱包在不安全的服务器中使用或者在每笔交易中发行不同的公共钥匙。公共钥匙不需要被预先加载或者提前衍生,而在服务器中不需要可用来支付的私钥。
2)种子和助记词(BIP-39)
HD钱包的所有的确定性都衍生自这个根种子。任何兼容HD 钱包的根种子也可重新创造整个HD钱包。所以简单的转移HD钱包的根种子就让HD钱包中所包含的成千上百万的密钥被复制,储存导出以及导入。在Bitbill注册时就会提示新建还是导入钱包,导入钱包即用这个助记词,所以一定要备份。
生成助记词过程:
a、创建一个128到256位的随机序列(熵)。
b、提出SHA256哈希前几位(熵长/ 32),就可以创造一个随机序列的校验和。
c、将校验和添加到随机序列的末尾。
d、将序列划分为包含11位的不同部分。
e、将每个包含11位部分的值与一个已经预先定义(2048个单词)的字典做对应。
f、生成的有顺序的单词组就是助记码。
生成种子:
a、PBKDF2密钥延伸函数的第一个参数是从步骤6生成的助记符。
b、PBKDF2密钥延伸函数的第二个参数是盐。 由字符串常数“助记词”与可选的用户提供的密码字符串连接组成。
c、PBKDF2使用HMAC-SHA512算法,使用2048次哈希来延伸助记符和盐参数,产生一个512位的值作为其最终输出。 这个512位的值就是种子。
从种子中创建钱包:
3)私有子密钥
分层确定性钱包使用CKD(child key derivation)函数去从母密钥衍生出子密钥。函数是基于单项哈希函数。这个函数结合了:
一个母私钥或者公共钥匙(ECDSA未压缩键)
一个叫做链码(256 bits)的种子 (链码是用来给这个过程引入确定性随机数据的,使得索引不能充分衍生其他的子密钥)
一个索引号(32 bits)
4)硬化子密钥
背景:简单地泄露的私钥以及一个母链码,可以暴露所有的子密钥。更糟糕的是,子私钥与母链码可以用来推断母私钥。
这个硬化衍生函数使用了母私钥去推导子链码,而不是母公钥。这就在母/子顺序中创造了一道“防火墙”——有链码但并不能够用来推算子链码或者姊妹私钥