# Go实现简单的区块链和数字签名流程

By [Untitled](https://paragraph.com/@0xc994df6bd78b5e78d4e820a57d65b4efd33bf936) · 2024-12-04

---

区块链的工作原理结合了多种技术，每种技术在链条的不同环节中发挥作用：

**1\. 非对称加密（椭圆曲线加密）**

     用于生成钱包地址和数字签名，保证交易的安全性和不可抵赖性。

          • 椭圆曲线算法（ECDSA）生成公私钥对，签署交易。

**2\. 哈希算法（Hash Function）**

     用于将任意长度的数据映射为固定长度的散列值（如 SHA256），确保数据完整性，并实现工作量证明（PoW）。

**3\. P2P 网络（Peer-to-Peer Network）**

     区块链通过 P2P 网络传播和同步数据，节点之间相互连接，不依赖中心服务器。

**4\. 分布式系统与共识机制**

     通过共识机制（如 PoW、PoS）确保所有节点对数据的一致性达成共识，防止双花攻击。

使用 Go 实现集成了非对称加密、哈希算法、P2P 网络和共识机制（PoW）的简单区块链系统。

    package main
    
    import (
        "crypto/ecdsa"
        "crypto/elliptic"
        "crypto/rand"
        "crypto/sha256"
        "encoding/hex"
        "fmt"
        "math/big"
        "strings"
        "time"
    )
    
    // Block 表示区块链中的单个区块
    type Block struct {
        Timestamp    int64  // 区块生成的时间戳
        PreviousHash string // 前一个区块的哈希值
        Hash         string // 当前区块的哈希值
        Data         string // 区块中存储的数据
        Nonce        int    // PoW 的随机数，用于找到符合难度的哈希
    }
    
    // 计算区块的哈希值
    func (b *Block) calculateHash() string {
        data := fmt.Sprintf("%d%s%s%d", b.Timestamp, b.PreviousHash, b.Data, b.Nonce)
        hash := sha256.Sum256([]byte(data))
        return hex.EncodeToString(hash[:])
    }
    
    // 工作量证明 (Proof of Work, PoW) 挖矿
    func (b *Block) mineBlock(difficulty int) {
        target := strings.Repeat("0", difficulty)
        for !strings.HasPrefix(b.Hash, target) {
            b.Nonce++
            b.Hash = b.calculateHash()
        }
        fmt.Printf("Block mined: %s\n", b.Hash)
    }
    
    // 创建新的区块
    func newBlock(data string, previousHash string) *Block {
        block := &Block{time.Now().Unix(), previousHash, "", data, 0}
        block.mineBlock(4) // 设置难度为4
        return block
    }
    
    // Blockchain 表示区块链
    type Blockchain struct {
        blocks []*Block
    }
    
    // 向区块链添加区块
    func (bc *Blockchain) addBlock(data string) {
        prevBlock := bc.blocks[len(bc.blocks)-1]
        newBlk := newBlock(data, prevBlock.Hash)
        bc.blocks = append(bc.blocks, newBlk)
    }
    
    // 创建创世区块
    func createGenesisBlock() *Block {
        return newBlock("Genesis Block", "0")
    }
    
    // 初始化区块链
    func newBlockchain() *Blockchain {
        return &Blockchain{[]*Block{createGenesisBlock()}}
    }
    
    // 生成ECDSA公私钥对
    func generateKeys() (*ecdsa.PrivateKey, *ecdsa.PublicKey) {
        privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
        return privateKey, &privateKey.PublicKey
    }
    
    // 使用私钥对消息签名
    func signMessage(privateKey *ecdsa.PrivateKey, message string) ([]byte, []byte) {
        hash := sha256.Sum256([]byte(message))
        r, s, _ := ecdsa.Sign(rand.Reader, privateKey, hash[:])
        return r.Bytes(), s.Bytes()
    }
    
    // 验证签名
    func verifySignature(publicKey *ecdsa.PublicKey, message string, rBytes, sBytes []byte) bool {
        hash := sha256.Sum256([]byte(message))
        var r, s big.Int
        r.SetBytes(rBytes)
        s.SetBytes(sBytes)
        return ecdsa.Verify(publicKey, hash[:], &r, &s)
    }
    
    func main() {
        // 1. 初始化区块链
        blockchain := newBlockchain()
    
        // 2. 生成公私钥对
        privateKey, publicKey := generateKeys()
    
        // 3. 签名交易
        message := "Transaction: Alice -> Bob 10 BTC"
        r, s := signMessage(privateKey, message)
    
        // 4. 验证签名，只有验证通过后才添加到区块链中
        if verifySignature(publicKey, message, r, s) {
            fmt.Println("Signature verified. Adding transaction to the blockchain...")
            signedMessage := fmt.Sprintf("%s\nSignature (r): %x\nSignature (s): %x", message, r, s)
            blockchain.addBlock(signedMessage) // 添加已验证的交易到区块链中
        } else {
            fmt.Println("Invalid signature. Transaction rejected.")
        }
    
        // 5. 打印区块链信息
        for i, block := range blockchain.blocks {
            fmt.Printf("Block %d:\n", i)
            fmt.Printf("\tTimestamp: %d\n", block.Timestamp)
            fmt.Printf("\tPrevious Hash: %s\n", block.PreviousHash)
            fmt.Printf("\tHash: %s\n", block.Hash)
            fmt.Printf("\tData: %s\n", block.Data)
        }
    }
    

**代码解读：**

• **区块链部分：**

     • 创建区块 (newBlock) 并通过工作量证明（PoW）机制挖矿。

     • 将新块添加到区块链 (addBlock)。

     • 创世区块是区块链的起点。

**• 加密签名部分：**

     • 使用椭圆曲线加密 (ECDSA) 生成公私钥。

     • 使用私钥签名消息，公钥验证签名。

• **运行结果：**

     • 区块链会生成两个新块，并输出每个区块的详细信息。

• 最后验证签名是否有效，输出签名验证结果。

---

*Originally published on [Untitled](https://paragraph.com/@0xc994df6bd78b5e78d4e820a57d65b4efd33bf936/go)*
