IPFS(InterPlanetary File System)是一个内容寻址、版本化、点对点的分布式文件系统。node
在官方网站下载对应平台的安装包,本文使用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
那么将在本目录下获得一张猫的图片安全
另外,能够在浏览器中访问http://localhost:5001/webui来使用ipfs的控制台
使用add
将一个文件添加到ipfs网络(能够被其余节点访问到)
> cat 187J3X1.txt Hello!187J3X1! > ipfs add 187J3X1.txt added QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj 187J3X1.txt
文件要能被网络中全部节点访问须要必定时间,在某个运行ipfs的节点,使用get
命令能够获取到本文件
> ipfs get QmRTxTkdXeUmG9GxJBA7B8Ad8hticjNwkucCY96mkzusXj
更多命令可查看帮助信息
> ipfs --help
能够从Github下载源码,自行编译安装
在ipfs文件系统中,只要知道文件的Hash,就能够从节点获取文件。因此ipfs天生缺少隐私性,加入须要分享私密的文件给别人。一般的作法是分享者将文件用接收者的公钥加密,接收者从ipfs网络下载后用私钥解密。GPG能够完成加解密的功能。
GPG一样可使用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
在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.io/ipns/输入节点的id
如今对文件进行修改,并添加到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显示新内容
ipns + 节点ID 显示新内容
ipfs + 旧Hash 显示旧内容
上面的例子中,咱们修改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文件内容。