【戴嘉乐】(上篇)运用Re-Encryption技术对你的IPFS网络数据进行多重保护

2019-01-08 22:11:03 浏览数 (1)

作者简介:戴嘉乐( Mr.Maple ) | 前百度高级研发工程师 | IPFS应用实践者&布道师|《中国IPFS开发者圆桌沙龙》举办人

一、研究背景

1.1 从HTTP到HTTPS的变迁来看:

从HTTP逐渐过渡到HTTPS的过程可以看出,网络中的明文传输始终具有不安全感,据我所知,从2015年开始,大部分互联网巨头公司都强制要求各产品线切换使用HTTPS(加密超文本传输协议),通过SSL/TLS完成双向加密,加固万维网上的安全通信,尤其是在交易支付场景下。

1.2 从IPFS网络的局限性来看:

IPFS有潜力成为区块链领域很棒的超级内容分发网络,本身IPFS也自带一些加密特性,但如果我们能通过一些有效的技术使得我们项目和业务在入网前(上传到IPFS网络前)前就加固一层安全属性,将大大提高IPFS网络的可用性和可信任性,让更多企业和用户愿意投入使用这项技术。

1.3 从行业内安全性角度来看:

行业安全性问题应当是每个开发者都该重视的方面(我们不能只顾着开发区块链业务,而忽视用户、投资者的安全隐患),随着区块链市场的不断扩大,整个生态的区块链项目也日益增多,同时,由于各个公司水平参差不齐,项目方做事的态度褒贬不一,不靠谱的区块链项目和合约漏洞数量也在与日俱增,类似美图这样的大公司之前也因为安全问题吃过大亏。

二、IPFS网络的Encryption层设计

2.1 具有PKI 特性

玩密码学的童鞋应该都不会陌生这个,PKI技术:Public Key Infrastructure ,也叫公钥基础设施,PKI是一种遵循标准的利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范。

  • HTTP协议中PKI的使用:可参考 HTTPS协议详解(三):PKI 体系
  • IPFS协议中PKI的使用:Node ID生成,IPNS挂载,私有集群网络搭建
2.1.1 PKI特性:Node ID生成

Eg:

代码语言:javascript复制
difficulty = <integer parameter> n = Node{} do { n.PubKey, n.PrivKey = PKI.genKeyPair() n.NodeId = hash(n.PubKey) p = count_preceding_zero_bits(hash(n.NodeId)) } while (p < difficulty)

这是IPFS白皮书中在初始化生成NodeID(n)时,所执行的一段伪代码:

我们可以看到,在创建过程中将通过PKI.genKeyPair()(默认用的RSA非对称加密算法)生成一套公钥(n.PubKey)和私钥(n.PrivKey),NodeId 将通过hash(n.PubKey)公钥进行签名。

这样做的好处是当Node 节点在第一次连接对等Peer方时,可以通过互相交换公钥,来验证hash(other.PublicKey) = other.NodeId是否成立 ,如果成立,则确定可信身份,保持通信,否则连接终止,防范网络中的一些嗅探***。(这和我们在做后端微服务之前的接口通信时,常设置变量参数参与的对称加密签名来防止网络***一样)

在本地,我们可以通过ipfs id随时来查看我们的公钥(PublicKey)和其对应的NodeID:

也可以通过vim ~/.ipfs/config 来进行私钥(PrivKey)的查看:

2.1.2 PKI特性:IPNS挂载

这里要提一下之前搬山工童鞋小密圈发起的一个提问: 如何在不同节点中更新同一个IPNS Hash的内容?的问题

我们直接使用

代码语言:javascript复制
ipfs name publish QmSomeHash

是默认挂载一个文件空间到的ipns/nodeID上,因为这边默认读取的公钥文件是生成NodeID的Self公钥,但是我们可以通过新生成一份代理公钥来实现不同节点中同一份IPNS地址的内容更新:

代码语言:javascript复制
//A节点生成mykey: ipfs key gen --type=rsa --size=2048 mykey //公钥一般存储在./ipfs/keystore 中 //拷贝mykey 至B节点同目录下,更新挂载点,更新内容 ipfs name publish --key=mykey QmSomeHash 

Type可选,默认是RSA,但也支持ed25519

代码语言:javascript复制
//From:https://github.com/ipfs/go-ipfs/blob/master/core/commands/keystore.go var sk ci.PrivKey var pk ci.PubKey switch typ { case "rsa": if !sizefound { res.SetError(fmt.Errorf("please specify a key size with --size"), cmdkit.ErrNormal) return } priv, pub, err := ci.GenerateKeyPairWithReader(ci.RSA, size, rand.Reader) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } sk = priv pk = pub case "ed25519": priv, pub, err := ci.GenerateEd25519Key(rand.Reader) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } sk = priv pk = pub default: res.SetError(fmt.Errorf("unrecognized key type: %s", typ), cmdkit.ErrNormal) return } 

2.1.3 PKI特性:私有集群网络搭建

通过官方提供的共享密钥生成工具:https://github.com/Kubuxu/go-ipfs-swarm-key-gen

代码语言:javascript复制
//From:https://github.com/Kubuxu/go-ipfs-swarm-key-gen/blob/master/ipfs-swarm-key-gen/main.go func main() { key := make([]byte, 32) _, err := rand.Read(key) if err != nil { log.Fatalln("While trying to read random source:", err) } fmt.Println("/key/swarm/psk/1.0.0/") fmt.Println("/base16/") fmt.Print(hex.EncodeToString(key)) } 

生成一份公共的swarm.key,存储在不同节点的上~/.ipfs/根目录下,

在我们添加完各个节点的bootstrap地址后,执行ipfs swarm connect操作后,会对公共密钥swarm.key进行再校验:

代码语言:javascript复制
//From:https://github.com/ipfs/go-ipfs/blob/master/core/commands/swarm.go for _, c := range conns { swcon, ok := c.(*swarm.Conn) if ok { ci.Muxer = fmt.Sprintf("%T", swcon.StreamConn().Conn()) } } 

  • 具体细节可以参考IPFS指南文章:私有网络的搭建与使用

虽然以上三个过程没有像HTTPS一样引入数字证书,但是也足够诠释了 PKI 的设计机制。

2.2 文件寻址加密

我们添加的地址 文件名都将通过Multihash模块加密映射成大家看到的Hash指纹,默认均采用sha2-256

代码语言:javascript复制
//From:https://github.com/ipfs/go-ipfs/blob/master/core/commands/add.go  Options: []cmdkit.Option{ ... cmdkit.StringOption(hashOptionName, "Hash function to use. Implies CIDv1 if not sha2-256. (experimental)").WithDefault("sha2-256"), }, 

Multihash支持多达10余种哈希算法,目前只在IPFS本地测试环境下才可配置:

代码语言:javascript复制
// From: https://github.com/multiformats/go-multihash/blob/master/multihash.go // Names maps the name of a hash to the code var Names = map[string]uint64{ "id":           ID, "sha1":         SHA1, "sha2-256":     SHA2_256, "sha2-512":     SHA2_512, "sha3":         SHA3_512, "sha3-224":     SHA3_224, "sha3-256":     SHA3_256, "sha3-384":     SHA3_384, "sha3-512":     SHA3_512, "dbl-sha2-256": DBL_SHA2_256, "murmur3":      MURMUR3, "keccak-224":   KECCAK_224, "keccak-256":   KECCAK_256, "keccak-384":   KECCAK_384, "keccak-512":   KECCAK_512, "shake-128":    SHAKE_128, "shake-256":    SHAKE_256, }

2.3 DAG分片

这块应该是IPFS内容寻址的设计精髓,当然,IPFS采用Merkle DAG技术对整个系统带来的优点有很多,今天这里我们只讨论DAG分片对文件的安全保护属性:

这是我之前上传的 自己的头像数据:Qmdv...

DAG分片之后:QmVo...,QmYG...QmdF...QmXA...QmSN...

我们拿到的一些分片文件是RAW格式(原始图像编码数据编码)的碎片文件,只获取其中的几个碎片数据是无法通过DAG解析器拼合成原图像的,一定意义上提升了网络中文件的安全性:

观察IPFS的Core层源码可以了解到:DAG解析器这部分,专门适配了四种格式:

  • json
  • raw
  • cbor
  • protobuf
代码语言:javascript复制
//From :https://github.com/ipfs/go-ipfs/blob/master/core/coredag/dagtransl.go // DagParser is function used for parsing stream into Node type DagParser func(r io.Reader, mhType uint64, mhLen int) ([]ipld.Node, error) // FormatParsers is used for mapping format descriptors to DagParsers type FormatParsers map[string]DagParser // InputEncParsers is used for mapping input encodings to FormatParsers type InputEncParsers map[string]FormatParsers // DefaultInputEncParsers is InputEncParser that is used everywhere var DefaultInputEncParsers = InputEncParsers{ "json":     defaultJSONParsers, "raw":      defaultRawParsers, "cbor":     defaultCborParsers, "protobuf": defaultProtobufParsers, }

2.4 More

当然IPFS的Encryption层还有很多其他的设计,可能我还没研究到,如果大家有新发现,可以随时联系我,一起探讨。

三、Re-Encryption技术

Re-Encryption:重加密技术起源于云计算时代对HTTP网络数据的安全性需求激增(大量用户参与,不可避免出现了隐私问题),因此而诞生的再加密技术,即:在原有的常用加密手段上对用户的隐私实现明文保密、公钥保密、防非法公钥替换、防合法公钥替换、别名无关性(除了你,任何实体都不能够判断不同别名是否对应同一个ID)等。

Eg:如果业务方A向业务方C发送一个在代理方B的密钥下加密的消息,代理B将通过提供密钥来授权业务方C解密消息内容,以得到明文。譬如:用户的实时位置数据通过手机定位存储在手机客户端中,我们将在客户端中根据用户ID或者Cuid生成私钥,自动加密定位数据再存储在IPFS上,由于数据采用的是我的密钥进行的再加密,除非我授权(即:将密钥共享),哪怕IPFS的哈希指纹暴露,任何第三方都无法访问我的数据内容。特别适合如内容授权分发这样的场景。

3.1 常见的加密技术:

3.1.1、对称加密

有流式、分组两种,加密和解密都是使用的同一个密钥。

例如:DES、AES-GCM、ChaCha20-Poly1305等

3.1.2、非对称加密

加密使用的密钥和解密使用的密钥是不相同的,分别称为:公钥、私钥,公钥和算法都是公开的,私钥是保密的。非对称加密算法性能较低,但是安全性超强,由于其加密特性,非对称加密算法能加密的数据长度也是有限的。

例如:RSA、DSA、ECDSA、 DH、ECDHE

3.1.3、哈希算法

将任意长度的信息转换为较短的固定长度的值,通常其长度要比信息小得多,且算法不可逆。

例如:MD5、SHA-1、SHA-2、SHA-256 等

3.1.4、数字签名

签名就是在信息的后面再加上一段内容(信息经过hash后的值),可以证明信息没有被修改过。hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。

四、为何需要对IPFS网络进行Re-Encryption

4.1 满足特异性

  • 协议实验室虽然已经考虑到了很多细节,并为此进行了最初的Crypto层设计,但这是局部的抽象方案,没法满足特例。

4.2 满足敏感性

  • 用户数据隐私一直是存储界的热议话题和痛点,也是政策最关心的边界。

4.3 满足适用性

  • IPFS技术是为多种生态技术服务的,存在繁多的业务(eg:数据分享)和技术场景,类型不一样,需要搭配不同的Re-Encryption技术方案。

系列篇预告

《【应用】(中篇)运用Re-Encryption技术对你的IPFS网络数据进行多重保护》

  • 几种对于IPFS网络的Re-encryption思路
    • 需要隐藏 Node ID 的场景:
    • 需要隐藏 Hash 指纹的场景:
    • 需要隐藏 File 内容的场景
    • 需要隐藏 Object 结构的场景

《【应用】(下篇)运用Re-Encryption技术对你的IPFS网络数据进行多重保护》

  • 工程实践为主:
    • 加密算法综合比较
    • 几种再加密技术对于IPFS网络实测性能综合比较
    • 如何配合IPFS官方API使用
    • 适合集成进哪些公司业务场景

一些题外话:感谢近期一些朋友的关心和青睐,这里做一个郑重的统一声明:本人2月份从百度离职后,一直处在自由职业的状态,每天的时间除了少部分在打理自己的OneMix基金,更多的是想静下心来做一些技术沉淀和知识积累工作,目前没有加入任何主体公司&机构,没有直接参与任何商业形式的项目&硬件研发(只为一些IPFS相关产品&公司提供技术咨询和顾问支持),很喜欢目前的一种生活状态,也很喜欢目前所在做的一些开源社区属性事情(开发者技术氛围营造,举办开发者沙龙,公益技术文章输出,开源项目分享等),如果后续要切换工作状态,会第一时间发布在朋友圈和最新的文章中,可能会和一些前辈成立加入类似 区块链实验室区块链技术研究院这样的科研组织。

参考文献

  • 张首晟教授:区块链又让一个网络去中心化的时代来临
  • 中国IPFS开发者圆桌沙龙:×××吴 基于IPFS的重前端应用
  • Proxy Re-Encryption Wikipedia
  • Learn to securely share files on the blockchain with IPFS (需要访问外国网站访问)
  • 区块链不只有去中心化:基于 IPFS 加密的去中心化数据应用落地分析
  • 学会通过IPFS在区块链上安全地分享文件
  • Textile Photos: your photos, decentralized and encrypted 
  • ED25519

相关文章和视频推荐

圆方圆学院汇集大批区块链名师,打造精品的区块链技术课程。 在各大平台都长期有优质免费公开课,欢迎报名收看。

公开课地址:https://ke.qq.com/course/345101?flowToken=1007371

0 人点赞