第18章 【IPFS一问一答】IPFS底层架构解析之身份层

18 IPFS底层架构解析之身份层

每个IPFS节点都有自己的身份,身份用NodeID表示。节点在加入IPFS网络前,首先要生成自己的身份。通过S/Kademlia静态加密算法产生一个公钥,然后通过hash运算到的值就是NodeID。用C++语言描述NodeID的生成过程:

//设定一个难度系数,即先导0的个数
difficulty =< integer parameter >
//初始化一个节点
n= Node{}
//循环运算,直到满足条件hash(NodeID)运算后的值的先导0的个数≥设定的先导0个数
do{
//产生公私钥对
n.PubKey, n.PrivKey = PKI.genKeyPair() 
//对公钥进行hash运算,得到未验证的NodeID
n.NodeId = hash(n.PubKey)
//判断NodeID的合法性,验证通过,循环结束
p = count_preceding_zero_bits(hash(n.NodeId)) }while(p<difficulty)

从上边的过程我们知道,节点会不断的产生公私钥对,直到公钥的hash运算值满足要求才会停止。而最后的公钥hash运算的值就是本机作为ipfs节点的NodeID。

在终端运行ipfs id会显示本机的ipfs节点信息,如下:

$ ipfs id
{
    "ID": "QmXdSpUBx9Ut6q8LF8Wyt1Wi2wxmob6qnnT11uV3SmvUP3",
    "PublicKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCh7fHOV1X0LEsqxxlY+wRRuMGZ+E7sMAWXfMj8NLenv3KpIX8pHy0lk/H6VCCjKB+t4e2Rb+Px9Uwh2YjRlLaaMkBYN27COVBdtL9sH5ZW2BZ6x00Deg+gWoO0xs5rzadtk45vV44RzxYDuGCT0GW79WgTBUi0s1O00LE6p+wOrZdk6UGYjUEzL3nD6CRMPoQbVtV8WGBWFksoyM+bnlyyCcFhw0suN5Yf8OicwGIDznsjniSOrku9QpoFU1B96SKMmfqiXZC+KyzFfKp/U1lFmfp7wlYObUYpMkcWI0/bRzdursQGga7xXyKwQJ5ZGouSANt6cClTMnOUHGLCFzzNAgMBAAE=",
    "Addresses": null,
    "AgentVersion": "go-ipfs/0.4.18/",
    "ProtocolVersion": "ipfs/0.1.0"
}

用户可以通过删除本机的ipfs节点信息文件,再初始化(命令是ipfs init)来重新设定新的身份。但是这样做会损失掉之前身份的所有网络利益。

当IPFS网络中的节点首次进行连接时,彼此会互换自己的公钥,然后对对方的公钥进行hash运算,即hash(other.PubKey),如果得到的值等于对方的NodeID,那么说明对方是合法的ipfs节点,彼此互连,反之连接被终止。

这里说的hash函数得到的值是个自我描述的值,如QmXdSpUBx9Ut6q8LF8Wyt1Wi2wxmob6qnnT11uV3SmvUP3,这个值是经过Base58编码后的值。读者可能会注意到,所有的散列都是以“Qm”开头的。这是因为它实际上是一个multihash,前两个字节用于指定哈希函数和哈希长度。前两个字节的十六进制是1220,其中12表示这是SHA256哈希函数,20代表哈希函数选择32字节长度计算。