文章目录
1.文章修改声明
由于需要遵循CSDN平台的社区规定,本文章进行了一些删减和修改,感谢阅读。
2.区块链的原理
(1).默克尔树
哈希树或默克尔树是一棵树,其中每个叶节点都用数据块的密码哈希标记,每个非叶节点都用其子节点标签的密码哈希标记。 。哈希树允许对大型数据结构的内容进行有效且安全的验证。哈希树是哈希列表和哈希链的概括。为了证明叶节点是给定的二进制哈希树的一部分,需要计算与该树的叶节点数量的对数成正比的哈希数,这与哈希列表相反,哈希列表的数量与叶节点本身的数量成正比。
这个是二进制哈希树的示例。哈希0-0和0-1分别是数据块L1和L2的哈希值,哈希0是哈希0-0和0-1串联的哈希。
(2).区块和区块链
在区块链里有很多区块,这些区块被使用链接加密,每一个区块都包含一个区块的头部和交易信息(通常用默克尔树表示),在头部信息里包含了hash数列,时间戳。根据设计,区块链可以抵抗其数据的修改。这是因为一旦记录,任何给定块中的数据都无法追溯更改,而无需更改所有后续块。
从逻辑上讲,区块链可以看作是由5层组成:
1.基础架构(硬件)
2.网络(节点发现,信息传播和验证)
3.共识(工作证明,持股凭证)
4.数据(块,交易)
5.应用程序 (dApps)
因为任何给定块中的数据都无法追溯更改,而无需更改所有后续块。针对这一点
区块链的形成。主链(黑色)由从创始区块(绿色)到当前区块的最长的一系列区块组成。主链之外存在孤立块(紫色)。
允许参与者独立且相对便宜地验证和审核交易。使用对等网络和分布式时间戳服务器自主管理区块链数据库。他们认证通过大规模协作搭载集体自身利益。这样的设计促进了健壮的工作流程,其中参与者对数据安全性的不确定性是微不足道的。区块链的使用消除了数字资产无限重现的特征。它确认了每个价值单位仅转移了一次,从而解决了长期存在的双重支出问题。区块链已被描述为一种价值交换协议。区块链可以维护所有权,因为当正确设置以详细说明交换协议时,它可以提供强制要约和接受的记录。
一个简单的例子:在ABCD四个人里发起了交易。其中A转给了B100个Bitcoin。因为这是去中心化的记账方式。所以在这四个人每个人自己的账本上都会有记录这笔交易,都会记录了A转给了B100个Bitcoin。这就是一条会被记录区块的交易信息每一个区块的大小为1MB,可以存放大约4k条信息。 在这个区块里我为什么会以A为准来通知其他人呢?平时交易里我们将会将谁为准呢?还有我们为什么要记账呢?对我们有什么好处吗?这些都是在设计上会遇到的问题。
3.每个区块谁是所谓的"中心"
(1).通过工作量证明机制来获得打包的权力
中本聪在论文中也写到了,每个用户或者节点会通过工作量证明的机制来争夺记账的权力。每个区块第一个可以计算出来的用户就是下一个区块的产生者。通过工作量证明来选择用户的唯一方法就是让用户解决”数学“问题。这个数学问题是基于SHA256算法的问题,所以唯一的办法只能一个一个尝试,谁最先得到这个问题的答案,谁就可以获得打包的资格。
(2).SHA256算法
安全哈希(SHA)算法是由美国国家标准技术研究院作为美国联邦信息处理标准发布的一系列加密哈希函数SHA代表安全哈希算法。SHA-1和SHA-2是该算法的两个不同版本。它们在结构(从原始数据创建结果散列的方式)和签名的位长方面都不同。SHA-2视为SHA-1的后继产品,因为它是一个整体改进。首先,人们把位长作为重要的区别。SHA-1是一个160位的哈希。SHA-2实际上是一个“哈希”系列,并具有各种长度,最流行的是256位(SHA256),最终输出的是一个256位的二进制数。以下是SHA256算法的伪代码:
Initialize hash values:
(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
Initialize array of round constants:
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
k[0..63] :=
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
Pre-processing (Padding):
begin with the original message of length L bits
append a single '1' bit
append K '0' bits, where K is the minimum number >= 0 such that L + 1 + K + 64 is a multiple of 512
append L as a 64-bit big-endian integer, making the total post-processed length a multiple of 512 bits
such that the bits in the message are L 1 00..<K 0's>..00 <L as 64 bit integer> = k*512 total bits
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
create a 64-entry message schedule array w[0..63] of 32-bit words
(The initial values in w[0..63] don't matter, so many implementations zero them here)
copy chunk into first 16 words w[0..15] of the message schedule array
Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
for i from 16 to 63
s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
s1 := (w[i- 2] rightrotate 17) xor (w[i- 2] rightrotate 19) xor (w[i- 2] rightshift 10)
w[i] := w[i-16] + s0 + w[i-7] + s1
Initialize working variables to current hash value:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7
Compression function main loop:
for i from 0 to 63
S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
ch := (e and f) xor ((not e) and g)
temp1 := h + S1 + ch + k[i] + w[i]
S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
maj := (a and b) xor (a and c) xor (b and c)
temp2 := S0 + maj
h := g
g := f
f := e
e := d + temp1
d := c
c := b
b := a
a := temp1 + temp2
Add the compressed chunk to the current hash value:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h
Produce the final hash value (big-endian):
digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
(3).通过C++语言形成的SHA256核心算法代码
#pragma once
#ifndef SHA256_H
#define SHA256_H
#include <string>
class SHA256
{
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint32 sha256_k[];
static const unsigned int SHA224_256_BLOCK_SIZE = (512 / 8);
public:
void init();
void update(const unsigned char* message, unsigned int len);
void final(unsigned char* digest);
static const unsigned int DIGEST_SIZE = (256 / 8);
protected:
void transform(const unsigned char* message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2 * SHA224_256_BLOCK_SIZE];
uint32 m_h[8];
};
std::string sha256(std::string input);
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA256_F1(x) (SHA2_ROTR(x, 2) ^ SHA2_ROTR(x, 13) ^ SHA2_ROTR(x, 22))
#define SHA256_F2(x) (SHA2_ROTR(x, 6) ^ SHA2_ROTR(x, 11) ^ SHA2_ROTR(x, 25))
#define SHA256_F3(x) (SHA2_ROTR(x, 7) ^ SHA2_ROTR(x, 18) ^ SHA2_SHFR(x, 3))
#define SHA256_F4(x) (SHA2_ROTR(x, 17) ^ SHA2_ROTR(x, 19) ^ SHA2_SHFR(x, 10))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8) ((x) ); \
*((str) + 2) = (uint8) ((x) >> 8); \
*((str) + 1) = (uint8) ((x) >> 16); \
*((str) + 0) = (uint8) ((x) >> 24); \
}
#define SHA2_PACK32(str, x) \
{ \
*(x) = ((uint32) *((str) + 3) ) \
| ((uint32) *((str) + 2) << 8) \
| ((uint32) *((str) + 1) << 16) \
| ((uint32) *((str) + 0) << 24); \
}
#endif
4.区块链和其应用的安全
区块链安全吗?它们是如何防止伪造,篡改和双重支付呢?身份认证技术在生活中可以是人脸识别、签字、指纹等。但是它们一旦数字化,都可以通过复制的方法伪造,所以区块链采用了电子签名的方法。电子签名技术主要采用了非对称加密方式。首先区块链会产生随机数,这项技术会通过随机数产生私钥(只有用户自己知道)通过私钥进行加密,再通过私钥产生公钥(可以公开的)可以通过公钥进行解密,最后会产生一个公开的地址,用户就可以通过地址进行匿名的交易了。典型的算法是RSA,区块链采用椭圆曲线加密算法。
转换过程
1、首先使用随机数发生器生成一个私钥,它是一个256位的二进制数。私钥是不能公开的,相当于银行卡的密码。 2、私钥经过SECP256K1算法生成公钥,SECP256K1是一种椭圆曲线加密算法,功能和RSA算法类似,通过一个已知的私钥,生成一个公钥,但是通过公钥不能反推出私钥。 3、同SHA256算法一样,RIPEMD160也是一种HASH算法,由公钥可以得到公钥的哈希值,而通过哈希值无法推出公钥。 4、将一个字节的版本号连接到公钥哈希头部,然后对其进行两次SHA256运算,将结果的前4字节作为公钥哈希的校验值,连接在其尾部。 5、将上一步的结果使用BASE58进行编码,就得到了钱包地址(相当于银行账户)。比如A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
(1).解决伪造的交易记录
(2).防止篡改交易记录
为了防止篡改事件的发生,区块链会根据最长链原则来保护整个区块链:
也就是说明在区块链出现分支的地方会比较上下链谁先挖出第二个区块(谁的链最先变成长的支链),长的保留,短的放弃。
所以我们可以根据最长链原则,如果有人想篡改区块链上某一区块的信息,他就要在该区块处引出一条分支,并且打造一条新链使得新链超过原链长度。即他一人控制的矿机算力要超过全世界剩余的矿机算力对抗(比谁更快)。这个实现的概率很小。就比如一个人控制了世界上90%的机器去篡改一条链的交易记录,为何他不利用这么多的机器去正经的开发货币呢?
(3).防止双重支付的交易
版权声明
本文被以下参考引用内容外均为J0hn原创内容,最终解释权归原作者所有。如有侵权,请联系删除。未经本人授权,请勿私自转载!
5.参考资料
[1]. BMoney http://www.weidai.com/bmoney.txt
[2]. Wikipedia https://en.wikipedia.org/wiki/Bitcoin
[3]. Wikipedia https://en.wikipedia.org/wiki/SHA-2
[4]. Wikipedia https://en.wikipedia.org/wiki/Blockchain
[5]. Youtube https://www.youtube.com/watch?v=g_fSistU3MQ&t=11s
[6]. BitcoinOrg https://bitcoin.org/bitcoin.pdf