Decentralized Net Framework

作者: 51reboot | 来源:发表于2018-09-07 15:01 被阅读2次

去中心化的互联网,首先需要革CA(Certification Authority)的命

1977年,MIT教授 Rivest, Shamir 和 Adleman 发明了三人名字命名的RSA算法,开创了非对称加密算法实用化的新时代。

2002年,Rivest, Shamir 和 Adleman 三人获得当年的图灵奖。


非对称加密

对于外行来说非对称密码算法比较玄妙,通常我们容易接受『一把钥匙开一把锁』,但对于非对称加密算法来说这里变成了『两把钥匙:一把上锁,一把解锁』

非对称加密解密

对于外行来说非对称密码算法比较玄妙,通常我们容易接受『一把钥匙开一把锁』,但对于非对称加密算法来说这里变成了『两把钥匙:一把上锁,一把解锁』

参考之前专门写过一篇 加解密(Encryption)& 哈希(Hash)算法----入门指引

非对称加密算法(Asymmetric Cryptography)是现代密码学的绝对的基石。基于非对称加密算法,我们伟大的程序员们发明出了很多有意思的东西:

  • 利用 非对称加密 + 对称加密 + 哈希,我们搞出了『数字签名』。
  • 利用 非对称加密 + 密钥交换 + 对称加密 + 哈希,我们搞出了SSL/TLS 和 HTTPS。
  • 利用 数字签名 + HTTPS,他们搞出了CA(Certification Authority),躺着数钱。
  • 利用 非对称加密 + 哈希 + P2P,中本聪搞出了Bitcoin。

那么,如果DHT(Distributed Hash Table)遇上 非对称加密 + 密钥交换 + 对称加密 + 哈希会有什么有趣的东西产生呢?

Certification Authority

我们知道,传统的TLS/SSL需要一个层级化的CA系统,类似于一个传销系统的金字塔,根证书(Root CA)给下一层CA签名做签名,最后一层CA给网站做签名。

这样就导致了,如果你能控制一个CA,那么很多中间人攻击的勾当就可以悄无声息的进行了。参见:

人构成的组织,反而成为了最大的漏洞。

继续聊下去之前,我们必须提一下DH算法https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange。我们不关心他的原理,简单来说,这个算法实现了这么一个功能:

DH(A.Public, B.Private) == DH(B.Public, A.Private)

通过这个几乎可以和RSA比肩的伟大发明,Alice可以仅获取Bob的Public Key并结合自己的Private Key来计算出一个和Bob用同样方式计算的相同密钥。

那么剩下的问题就在于如何防止在获取Bob的Public Key的时候被调包,也就是黑客们常说的MITM攻击(Man-in-the-middle attack)。

CA在HTTPS中的作用主要是作为一个中介,防止MITM。大致方式就是浏览器或操作系统把常见的CA的公钥放在预先存起来。访问使用HTTPS的网站的时候通过相应的根证书进行验证。

MacOS root CA

Decentralize

在构建CovenantSQL的时候我们对这个问题进行了思考,于是抛弃了CA创造了DH-RPC。

DH-RPC = DHT + ECDH + RPC

在DH-RPC里我们都用NodeID来作为URI(Uniform Resource Identifier),NodeID是通过Node的PublicKey上一个256位的随机数(NodeNonce)做两层不同的哈希生成的。

NodeID := sha256(blake2b-512(NodePublicKey + Uint256Nonce))

生成的NodeID大致长这个样子:

0000000004e249292693ee2eb89e1cfc4b05a211f0b0ff0ecbb9d5bc155c078f

NodeID:AddrNodeID:PublicKey存储在DHT上,为了防止针对DHT的各种女巫攻击 和 日食攻击,我们参考Bitcoin的思想,把NodeID前面连续的0的个数定义为难度,并且可以对允许存储在DHT上的NodeID难度进行一定的最低限制。

我们采用了Bitcoin使用的Elliptic Curve Secp256k1作为非对称加密算法。AES-256-CBC作为对称加密算法。

首先,Alice通过可信途径获取到Bob的NodeID,并在DHT上查询出Bob的网络地址和公钥。此时Alice已经得到了DH算法所需的Alice的私钥、Bob的公钥。

Alice向Bob发起连接,在RPC的TCP连接建立完成之后,连接发起方(Alice)首先会把一个自己的NodeIDNodeNonce发送给对端(Bob)。Bob收到Alice的NodeID之后通过查询DHT获取到Alice之前存储在DHT上的Alice.PublicKey并缓存在本地。Bob通过Alice发过来的NodeNonce和DHT上获取的Alice.PublicKey可以验证Alice的公钥是否是约定的算法生成的。此时Bob也获取到了DH算法所需的Bob的私钥、Alice的公钥。此时的Alice和Bob的通信就是经过高强度加密并且P2P的了。

流程图如下:

DH-RPC交互时序图

如果有黑客尝试覆盖Alice在DHT上的信息的方式进行MITM,由于NodeNonce验证NodeIDECDH的特性,黑客在没有Alice.PrivateKey的前提下是没有办法获取到通信加密用的对称密钥的。

当然,重放攻击等常见攻击手法也是在框架中进行了防御,不在我们的重点讨论之内。

Features

CovenantSQL几乎所有的网络通信都是构建在DH-RPC上的,其它DH-RPC的特性还包括:

  • 100% compatible with Go net/rpc standard.

  • ID based routing and Key exchange built on Secure Enhanced DHT.

  • use MessagePack for serialization which support most types without writing Marshal and Unmarshal.

  • Crypto Schema

  • Use Elliptic Curve Secp256k1 for Asymmetric Encryption

  • ECDH for Key Exchange

  • PKCS#7 for padding

  • AES-256-CBC for Symmetric Encryption

  • Private key protected by master key

  • Annoymous connection is also supported

  • DHT persistence layer has 2 implementations:

  • BoltDB based simple traditional DHT

  • Kayak based 2PC strong consistent DHT

  • Connection pool based on Yamux, make thousands of connections multiplexed overOne TCP connection.

Example

示例写了一个简单的P2P聊天节点,简单的改造一下应该就可以构建一个去中心化的聊天App了。

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"

    "github.com/CovenantSQL/CovenantSQL/conf"
    "github.com/CovenantSQL/CovenantSQL/proto"
    "github.com/CovenantSQL/CovenantSQL/route"
    "github.com/CovenantSQL/CovenantSQL/rpc"
    "github.com/CovenantSQL/CovenantSQL/utils/log"
)

// TestService to be register to RPC server
type TestService struct {
}

func NewTestService() *TestService {
    return &TestService{}
}

func (s *TestService) Talk(msg string, ret *string) error {
    fmt.Println(msg)
    resp := fmt.Sprintf("got %s", msg)
    *ret = resp
    return nil
}

func main() {
    //log.SetLevel(log.DebugLevel)
    conf.GConf, _ = conf.LoadConfig(os.Args[1])
    log.Debugf("GConf: %#v", conf.GConf)

    // Init Key Management System
    route.InitKMS(conf.GConf.PubKeyStoreFile)

    // Register DHT service
    server, err := rpc.NewServerWithService(rpc.ServiceMap{
        "Test": NewTestService(),
    })
    if err != nil {
        log.Fatal(err)
    }

    // Init RPC server with an empty master key, which is not recommend
    addr := conf.GConf.ListenAddr
    masterKey := []byte("")
    server.InitRPCServer(addr, conf.GConf.PrivateKeyFile, masterKey)

    // Start Node RPC server
    go server.Serve()

    // Register Node public key, addr to Tracker(BP)
    for _, n := range conf.GConf.KnownNodes {
        client := rpc.NewCaller()
        reqA := &proto.PingReq{
            Node: n,
        }
        respA := new(proto.PingResp)
        err = client.CallNode(conf.GConf.BP.NodeID, "DHT.Ping", reqA, respA)
        if err != nil {
            log.Fatal(err)
        }
        log.Debugf("respA: %v", respA)
    }

    // Read target node and connect to it
    scanner := bufio.NewScanner(os.Stdin)
    fmt.Print("Input target node ID: ")
    scanner.Scan()
    if scanner.Err() == nil {
        target := proto.NodeID(strings.TrimSpace(scanner.Text()))
        pc := rpc.NewPersistentCaller(target)
        log.Debugf("connecting to %s", scanner.Text())

        fmt.Print("Input msg: ")
        for scanner.Scan() {
            input := scanner.Text()
            log.Debugf("get input %s", input)
            repSimple := new(string)
            err = pc.Call("Test.Talk", input, repSimple)
            if err != nil {
                log.Fatal(err)
            }
            log.Infof("resp msg: %s", *repSimple)
        }
    }
}

Tracker代码请移步这里:CovenantSQL/CovenantSQL ,欢迎关注DH-RPC的Github:

https://github.com/CovenantSQL/CovenantSQL/tree/develop/rpc

首发地址:Decentralized Net Framework

最新公告通知

第 8 期 【Python自动化运维进阶】正在火热招生中

了解详情可添加小助手微信,备注“来源简书”

相关文章

网友评论

    本文标题:Decentralized Net Framework

    本文链接:https://www.haomeiwen.com/subject/hcjcgftx.html