IPFS 使用全记录

IPFS是什么

IPFS(InterPlanetary File System)是一个内容寻址、版本化、点对点的分布式文件系统。node

  • 内容寻址 - 文件不是以URL寻址,而是根据文件内容的Hash值寻址,一旦内容肯定,文件地址也就肯定
  • 版本化 - 相似于git,能够跟踪文件的历史变化状况
  • 点对点 - 全部运行ipfs的设备点对点组成一个去中心化网络

安装启动IPFS

bin包安装

官方网站下载对应平台的安装包,本文使用linux-64位版本
安装linux

或直接使用网址下载git

> wget https://dist.ipfs.io/go-ipfs/v0.4.15/go-ipfs_v0.4.15_linux-amd64.tar.gz

解压安装包,将可执行文件放在环境变量目录github

> tar xvfz go-ipfs_v0.4.15_linux-amd64.tar.gz
> mv ipfs /usr/local/bin/

初始化ipfs节点web

> ipfs init
initializing ipfs node at /root/.go-ipfs
generating 2048-bit RSA keypair...done
peer identity: QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
to get started, enter:

  ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme

根据提示,检查安装状态redis

> ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme
Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

 -------------------------------------------------------
| Warning:                                              |
|   This is alpha software. use at your own discretion! |
|   Much is missing or lacking polish. There are bugs.  |
|   Not yet secure. Read the security notes for more.   |
 -------------------------------------------------------

Check out some of the other files in this directory:

  ./about
  ./help
  ./quick-start     <-- usage examples
  ./readme          <-- this file
  ./security-notes

前面完成了ipfs节点的配置,接下来就是启动ipfs守护进程,能够在另外一个终端启动,也能够在本终端加上后台启动ubuntu

> ipfs daemon
Initializing daemon...
Successfully raised file descriptor limit to 2048.
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/172.17.0.1/tcp/4001
Swarm listening on /ip4/172.22.16.1/tcp/4001
Swarm listening on /ip4/192.168.0.116/tcp/4001
Swarm listening on /ip4/192.168.122.1/tcp/4001
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /p2p-circuit/ipfs/QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
Swarm announcing /ip4/10.103.255.235/tcp/48240
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/172.17.0.1/tcp/4001
Swarm announcing /ip4/172.22.16.1/tcp/4001
Swarm announcing /ip4/192.168.0.116/tcp/4001
Swarm announcing /ip4/192.168.122.1/tcp/4001
Swarm announcing /ip6/::1/tcp/4001
API server listening on /ip4/127.0.0.1/tcp/5001
Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
Daemon is ready

在另外一个终端输入如下命令确保链接进ipfs网络api

> ipfs swarm peers
/ip4/103.214.109.178/tcp/4001/ipfs/QmfZeNauweuRYWNXMjPhB4Tu2CPU6aD5eide9PEhVtHP6A
/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
/ip4/104.223.59.174/tcp/4001/ipfs/QmeWdgoZezpdHz1PX8Ly8AeDQahFkBNtHn6qKeNtWP1jB6
/ip4/104.233.106.156/tcp/4001/ipfs/QmSaLHB9dK7UphxcSWSdySVQyayux2yVMUELnAN8VV96x2
/ip4/106.38.77.82/tcp/49777/ipfs/QmfT3BCVYjLiVVB197mR1P4uhdR7zsKZsE7HLzCV1qSbHJ
/ip4/107.172.55.210/tcp/4001/ipfs/QmcYfPreozdQMKyo5omUhvTShCKRjdeiQhS7328J7CLLXe
/ip4/109.129.112.32/tcp/56478/ipfs/QmRYXX6mvvQQWR1kB1pC5c5dbcwASqyoQ6sjxH2czzPNBs
......

到如今,已经能够从ipfs网络中获取文件了,以一个官方图片为例浏览器

> ipfs cat /ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg  > cat.jpg

那么将在本目录下获得一张猫的图片
cat安全

另外,能够在浏览器中访问http://localhost:5001/webui来使用ipfs的控制台

console

使用add将一个文件添加到ipfs网络(能够被其余节点访问到)

> cat 187J3X1.txt 
Hello!187J3X1!
> ipfs add 187J3X1.txt 
added QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj 187J3X1.txt

文件要能被网络中全部节点访问须要必定时间,在某个运行ipfs的节点,使用get命令能够获取到本文件

> ipfs get QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj

更多命令可查看帮助信息

> ipfs --help

源码安装

能够从Github下载源码,自行编译安装

使用GPG完成私密文件分享

在ipfs文件系统中,只要知道文件的Hash,就能够从节点获取文件。因此ipfs天生缺少隐私性,加入须要分享私密的文件给别人。一般的作法是分享者将文件用接收者的公钥加密,接收者从ipfs网络下载后用私钥解密。GPG能够完成加解密的功能。

GPG一样可使用bin包安装或源码安装

bin包安装

以ubuntu 为例

> sudo apt-get install gnupg

源码安装

(TODO)

密钥生成

接收者使用gen-key生成密钥对

> gpg --gen-key
gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

加密方案使用默认RSA就行

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection?

密钥长度依然选择默认

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)

设置密钥过时时间,选择永远不过时

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)

输入秘钥建立者一些信息

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: chenmo
Email address: 13688368470@163.com
Comment: 
You selected this USER-ID:
    "chenmo <13688368470@163.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

建立私钥密码(很是重要)

You need a Passphrase to protect your secret key.
Enter passphrase:
Repeat passphrase:

接下来,程序将开始生成密钥,为了使生成过程使用的随机数更加随机,你能够采用敲键盘、移动鼠标等方式增长随机数的随机特性。

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
f
Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 186 more bytes)

本机生成的秘钥对能够用--list-keys命令查看

gpg --list-keys
/root/.gnupg/pubring.gpg
------------------------
pub   2048R/F0AA19A1 2018-07-08
uid                  chenmo <13688368470@163.com>
sub   2048R/54C6ABC4 2018-07-08

其中的F0AA19A1就是公钥id, 54C6ABC4是私钥id

可使用armor命令将秘钥导出为filename文件

gpg --armor --output [filename] --export [密钥id]

密钥分享

接收者须要告诉发送者本身的公钥,以便发送者加密。这能够经过公钥服务器完成。本文使用
hkp://pgp.mit.edu

> gpg --send-keys [公钥id] --keyserver hkp://pgp.mit.edu
gpg: "--keyserver" not a key ID: skipping
gpg: "hkp://pgp.mit.edu" not a key ID: skipping
gpg: sending key [公钥id] to hkp server keys.gnupg.net

发送方搜索该密钥

> gpg --keyserver hkp://pgp.mit.edu -search-keys [公钥id]

加密文件

发送方加密待分享的文件ipfs_demo.txt

> cat ipfs_demo.txt
This file is just for test --- 187J3X1
> gpg --encrypt --recipient [公钥id] ipfs_demo.txt

将加密后的文件ipfs_demo.txt.gpg 添加到ipfs网络中

> ipfs add ipfs_demo.txt.gpg 
added QmbvjL7BnCpUgzrJj2E2QkhqRBJeWKmo1TCfpMmKEQMYYc ipfs_demo.txt.gpg

解密文件

接收方获取文件

>ipfs get QmQRLCz3c6BwtkcACxwwraDX62g4ZAS7fQmrn3Y3rJh1xN
Saving file(s) to QmQRLCz3c6BwtkcACxwwraDX62g4ZAS7fQmrn3Y3rJh1xN
 24 B / 24 B [======================================================] 100.00% 0s

该操做可能会有必定时间延时,也可经过网页访问文件地址来接收文件

接下来用私钥解密出原文件

gpg --decrypt QmbvjL7BnCpUgzrJj2E2QkhqRBJeWKmo1TCfpMmKEQMYYc > ipfs_demo.txt

You need a passphrase to unlock the secret key for
user: "chenmo <13688368470@163.com>"
2048-bit RSA key, ID 54C6ABC4, created 2018-07-08 (main key ID F0AA19A1)

gpg: encrypted with 2048-bit RSA key, ID 54C6ABC4, created 2018-07-08
      "chenmo <13688368470@163.com>"
> cat ipfs_demo.txt 
This file is just for test --- 187J3X1

添加文件

在ipfs守护进程启动以后,可使用ipfs add命令将文件添加到ipfs网络

> echo "Hello!187J3X1!" > 187J3X1.txt
> ipfs add 187J3X1.txt
added QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj 187J3X1.txt

其中QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj就是文件内容的Hash值,一旦文件内容改变,这个值就会改变。须要注意,这个值与文件名彻底没有关系,它只是内容的Hash,无论文件名是什么,只要内容同样,它的Hash值就是同样的。

本地位置

ipfs的本地存储空间在~/.ipfs,全部ipfs自身的文件和本地添加到ipfs网络的文件都存放在此目录

> ls /.ipfs
api  blocks  config  datastore  datastore_spec  keystore  repo.lock  version

今后目录下这里能够找到刚才添加的文件

grep -rn "187J3X1"
Binary file blocks/ZF/CIQIXJZ7NCVBEU67XHWSTICDNGNRD2SIAE33W4SSDI6LZTE4PLRSZFA.data matches

读取文件

使用ipfs cat命令能够获取添加到ipfs网络中的文件,若是文件内容就在本地,那么显示将会很快,若是是在另外一个节点,那么要等本节点从网络中得到该文件内容后,才会显示

> ipfs cat QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj
Hello!187J3X1!

能够将文件内容重定向到一个文件,文件名彻底没必要与原来的同样,由于在ipfs网络中存储的只有内容,没有文件名

> ipfs cat QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj > recv.txt
> cat recv.txt
Hello!187J3X1!

添加文件名信息

向ipfs网站中添加单个文件是没有文件名等信息的,经过在ipfs add命令中添加-w选项,能够将该文件的文件名和所处文件夹的信息一同添加到ipfs网络

> pwd
/home/yc/workspace/ipfs/tmp
> ipfs add -w 187J3X1.txt 
added QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj 187J3X1.txt
added Qmdjqtwaj2vFkQ4P49qbnR9ksFphkSvUEf3S5rPNDVo7Kn

与刚才仅添加一个文件不一样的是,这里会获得两个Hash值,第一个QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj是文件内容的Hash值,与以前的同样,另外一个Qmdjqtwaj2vFkQ4P49qbnR9ksFphkSvUEf3S5rPNDVo7Kn就是文件所处目录的信息的Hash值。

使用ipfs ls命令能够列出这种层次关系(不能使用ipfs cat)

ipfs ls -v Qmdjqtwaj2vFkQ4P49qbnR9ksFphkSvUEf3S5rPNDVo7Kn
Hash                                           Size Name
QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj 23   187J3X1.txt

能够利用目录和文件关系找到显示文件的内容

> ipfs cat Qmdjqtwaj2vFkQ4P49qbnR9ksFphkSvUEf3S5rPNDVo7Kn/187J3X1.txt
Hello!187J3X1!

添加目录

经过在ipfs add命令中添加-r选项,能够将一个目录和其中的内容添加到ipfs网络中

> pwd
/home/yc/workspace/ipfs/tmp
> echo "My Second file" > Second_file.txt
> ls
187J3X1.txt  Second_file.txt
> ipfs add -r .
added QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj tmp/187J3X1.txt
added QmT96ZpTMV9kjtfEySjovvnfi92NxRqkogVtiwtD5Xs7rX tmp/Second_file.txt
added QmZ813ofgBrNuUpH8VFCR4A8LVkp1vSZcmxnET5PqCtj65 tmp

能够看到该命令将整个目录的内容都添加到了ipfs网络,前两个Hash值是文件,最后一个Hash值是目录。经过'ipfs ls'查看

> ipfs ls -v QmZ813ofgBrNuUpH8VFCR4A8LVkp1vSZcmxnET5PqCtj65
Hash                                           Size Name
QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj 23   187J3X1.txt
QmT96ZpTMV9kjtfEySjovvnfi92NxRqkogVtiwtD5Xs7rX 23   Second_file.txt

IPNS是什么

ipfs中,一个文件的Hash值彻底取决于其内容,修改它的内容,其相应的Hash值也会发生改变。若是咱们把修改先后的文件都经过ipfs add添加到ipfs网络中,那么咱们将能够经过这两个Hash值访问到先后两个版本的内容。这种静态特性有利于提升数据的安全,好比 Alice 能够将一份本身签名(私钥加密)的文件放到ipfs中,那么即便她后来对文件进行了修改并从新签名和发布,那么以前的文件依然存在,她不能抵赖曾经发布过老版本的文件。但对于一些须要保持动态性的文件来讲,好比网页,在新版本出现后,旧版本的内容将毫无心义。而且,总不能要求网页访问者每次要在浏览器中输入不一样的ipfs地址来访问不一样时期的网页吧。

IPNS(Inter-Planetary Naming System)提供了一种为文件增长动态性的解决方案。它容许节点的PeerID限定的命名空间提供一个指向具体ipfs文件(目录)Hash的指针,经过改变这个指针每次都指向最新的文件内容,可使得其余人始终访问最新的内容。

例子

> echo "This is old version file" > myfile.txt 
> ipfs add myfile.txt
added QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR myfile.txt

使用ipfs publish命令发布本节点ipns到ipfs的映射

> ipfs name publish /ipfs/QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR
Published to QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR: /ipfs/QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR

QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR正是本节点的ID,这一点能够经过ipfs id看到

ipfs id
{
    "ID": "QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR",
    ......

使用命令ipfs resolve能够解析ipns到ipfs的映射关系

> ipfs name resolve QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
/ipfs/QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR

在本地执行该命令,很快就能够获得结果。若是在其余节点执行,会花费一些时间。
能够看出解析的结果正是myfile.txt文件的内容。

这一点也能够在浏览器中验证

在ipfs.io/ipfs/直接输入文件内容的Hash
ipfs

在ipfs.io/ipns/输入节点的id
ipns

如今对文件进行修改,并添加到ipfs网络

> echo "This is new version file" > myfile.txt 
> ipfs add myfile.txt
added Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb myfile.txt

再修改ipns到ipfs的映射关系,使本节点的id映射到新的文件内容Hash

> ipfs name publish Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb
Published to QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR: /ipfs/Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb

验证其映射关系

> ipfs name resolve QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
/ipfs/Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb

在浏览器中验证:

ipfs + 新Hash显示新内容
ipfs-new

ipns + 节点ID 显示新内容
ipns-new

ipfs + 旧Hash 显示旧内容
ipfs

上面的例子中,咱们修改ipns下的节点ID和ipfs文件内容的映射关系,使得虽然访问的是同一个地址但实际访问的文件内容却不相同,这不只适用于单个文件,咱们彻底能够对一个目录做这种操做。

可是一个节点的ID只有一个,假设我须要同时保留多个这样的映射实例,该怎么办呢?

其实ipns的映射关系除了节点ID<->文件内容,还有一种是key<->文件内容

经过ipfs key list命令能够看到本节点的key

> ipfs key list -l
QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR self

能够看到,节点默认具备一个名为self的key,它的值正是节点ID。

而在ipfs name publish命令的完整形式是

ipfs name publish [--resolve=false] [--lifetime=<lifetime> | -t] [--ttl=<ttl>] [--key=<key> | -k] [--] <ipfs-path>

注意其中的key,若是不带这个参数,那么久表示使用默认的key, 也就是节点ID。

可使用ipfs key gen建立新的key,这里建立一个名为another的key

> ipfs key gen --type=rsa --size=2048 another 
QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE
> ipfs key list -l
QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR self    
QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE another

尝试用新的key,映射一个ipfs文件内容

> echo "This is another file" > another.txt
> ipfs add another.txt 
added QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm another.txt

> ipfs name publish --key=another  QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm
Published to QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE: /ipfs/QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm

ipfs resolve解析

> ipfs resolve /ipns/QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE
/ipfs/QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm

小结

IPNS能够为ipfs的动态内容提供映射,用户经过publish操做,使得其余人访问固定的IPNS地址就能够最终访问到不一样的ipfs文件内容。

相关文章
相关标签/搜索