是否可以在不发布的情况下从 IPFS 密钥对派生 IPNS 名称?
Is it possible to derive an IPNS name from an IPFS keypair without publishing?
我们希望允许用户根据他们维护的 IPFS 密钥名称从 IPNS 指针恢复他们的数据库。但是,由于 IPNS name/resolve
和 name/publish,
只有两个端点,因此似乎无法在不重新指向 IPNS 名称的情况下从密钥中派生出 IPNS 名称。可能吗?
我发现密钥都存在于 IPFS_HOME
内的 keystore
fodler 中,但我不确定这些文件的格式。这里的评论表明它们是 protobuf 格式,但我不确定如何从那里有意义地提取数据。
例如,使用 --decode-raw
给我这个:
root@ip-172-31-11-196:~# protoc --decode_raw $IPFS_HOME/keystore/keypairfile
1: 0
2: "02[=10=]43[=10=]2[=10=]1[=10=]0[=10=]22[=10=]1[=10=]1[=10=]036v\+s01`8Y4Y3I7h4746Q6W7ZA771\t4?7Y2tP175^465Q1*[n[=10=]4Lh76F05yr1337D~14j23I[5rv4641WO72+3|674z<~2K524664+3JE61\n2,n56544224>355l703\6~*h73177P2744W;54pE670\t7564\'K7E35c50102176340}2J47+[=10=]736704>[31Z71\'4_o77244F47431NM1404D*-Pa5%136H15[=10=]453Q27[=10=]707362{772421q6[=10=]022222I1[=10=]2[=10=]3[=10=]1[=10=]0[=10=]1[=10=]22[=10=]1[=10=]0[=10=]2[=10=]37061437[=10=]75C0[=10=]31\&870F{7l26g6d#Xd5UK<16721%061+jq[=10=]173Ht24&0R[=10=]1`422a66\'462T?Z04p4a0{7Y21k7?`+;265=F6wP[=10=]6F_t34m105 2Q47F/76V2836}97M225Z%5[=10=]7076L63%3160P5\t72326572W27e3k?[=10=]144k236W79800741Ft5427^6k-)]eD1[=10=]727-J1\cJh6205\t2Q\0107q\t60${25y06\r44P72DR7[=10=]160$202xp1217*09\t220[=10=]1[=10=]211[=10=]01p|566*3%460i3Y[=10=]217$2g7WT!C52n7`\r\t3(q33K26X3B17p\t74|+_73k05[=10=]0Fr3pqW[=10=]1>G31y3p751K2>3]Od55034577R4GA66W1@*s05`>}713PU2]56]=6n[=10=]56P7w32[=10=]1[=10=]211[=10=]01mfm9y631>4[=10=]7C040200731|W05w3~\'SD9r27;)06)[X<XH1a408o14[=10=]70162,0e[=10=]1m00246u177714]2~{o0h@0(-7FF01X0[=10=]1*\t60355461g>6525H3706522(615c0371[=10=]210O9A70h77124NYD5m2O0g3y434014!:47700460200I0XZ600`5]65420)474`;kH2600347576,7045c[=10=]56636*2426<39(4OF3172E)7O[35234W262044766K6[=10=]1[=10=]210370\"673y01=424bH\r>016->0712tH0zF4771P\r67?a4175530\r2[=10=]6*4]41i404&7 q76y55WG6[22M6ZR54171222370645*5&26706#6\".&163>410@66676,4z215k1[=10=]211[=10=]01135006026G151!533\7N2[=10=]44>4\nP65-0b\6=4C\t723xC7P3443Xn400A3[=10=]1N233r[=10=]46v0v\"g545[=10=]1L;4,426247Z25)244771[=10=]45(60115[=10=]215Y4Cb%2uB337-kr567777+02"
这似乎是两个二进制项,但我仍然无法完全从...中提取 IPNS 名称,或者是吗?
这是一个 Go 中的工作示例,说明如何读取 RSA 密钥对和 base58 编码 public 密钥以获取 IPNS 对等 ID:
package main
import (
"bufio"
"bytes"
"encoding/pem"
"fmt"
"log"
"github.com/ipfs/go-ipfs/keystore"
b58 "github.com/mr-tron/base58/base58"
mh "github.com/multiformats/go-multihash"
)
func main() {
ks, err := keystore.NewFSKeystore("/Users/username/.ipfs/keystore/")
if err != nil {
log.Fatal(err)
}
priv, err := ks.Get("mykey")
if err != nil {
log.Fatal(err)
}
privBytes, err := priv.Bytes()
if err != nil {
log.Fatal(err)
}
var privPEM bytes.Buffer
privWriter := bufio.NewWriter(&privPEM)
pem.Encode(privWriter, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privBytes,
})
privWriter.Flush()
pub := priv.GetPublic()
var pubPEM bytes.Buffer
pubBytes, err := pub.Bytes()
pubWriter := bufio.NewWriter(&pubPEM)
pem.Encode(pubWriter, &pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pubBytes,
})
pubWriter.Flush()
privPEMString := string(privPEM.Bytes())
pubPEMString := string(pubPEM.Bytes())
var alg uint64 = mh.SHA2_256
maxInlineKeyLength := 42
if len(pubBytes) <= maxInlineKeyLength {
alg = mh.ID
}
hash, _ := mh.Sum(pubBytes, alg, -1)
peerID := b58.Encode(hash)
fmt.Println(privPEMString)
fmt.Println(pubPEMString)
fmt.Println("IPNS:", peerID)
}
输出:
-----BEGIN RSA PRIVATE KEY-----
CAASpwkwggSjAgEAAoIBAQDjwkdyAvwfL6zIr2O6MF2ipNd/pkkV+5+9wOyvAL9I
HY4WRMmmLBGiBTj1Kln79ttChegxy/XME7ipzt2KXq7qaMT7ZiscB0pPpLCpViue
GxY90VbYmTeUrtvFJ+fJ5k4InuYtxJpwIpK0zkTZEQbq7mjOOl0VaIzH4iBjKKDq
uYXxX5JSz5/9I2a4d5YvOoci703krFEAGw4FsnUR+NU0wKE2A66+t+xml3E6D/Oo
OowSzLk2o0vZOFqNG4/tas9HGKYO8ofmFYMhbw5j/p3lZCHhPdklZZ4nlrEZIxPT
lwdeY3qBG+7WyzctLbJLerg8cvwOJ5m46uQ4f0j4mYf9AgMBAAECggEAQPhftxdA
4oiQCmN12FwJqebKDoDZ4mp4BAIvwjA9YI4FxTZ0K3Hwyb4hpFYjeyvNGinmtaXQ
BRovGEmJivo9fWLLpkdbztAJk7SQLI4HPT/O1W2ND5aNc116FcCvbznCUtU5Jh8q
SwihvvAEVcN0rLm7rfCaMwwy9KX9xSuG0830suMmVJ31W0evzRYHtnsvmDC9rdrA
TOy2HZdbL5Bty+nSwOlD608hCPWG6jCH5/BpEA3nCGX6KGH4yqFjaWGRA54cGGsh
bcKP1Hsdk0zle+Epl04yR1h2XCuwfmM3yegZuKjG5dfF51kV0yq2kND4F47D5azp
QJEhYHHOi6dvhQKBgQDwhZVl0W1rZjUvzkf/mZ2uC7aL64Rg1DFWNpSc05NK4IBS
eAf17HCCxLHCZnR0r8+CC0bOR+0xFT24RKcDyiPzpUo90LKHV3CXZEeFEWwfCg6N
RUfKMVLu9Vf5z7U4V2lOkojE7pWLt/ZMEAxXByQPlNyARfiRI8HPsPgrTlJvKwKB
gQDyam+oJbAfLvEFQ+h0B1ov3/3BEzV3GRkRz/IHTzQvHKyrN8zn/NZzQfrv3GR8
5W9BumpdfPkV5kCJb00fjS7AgLGWGHBsqzyDdliZdiQ5h5b15SflDrzfCF6c23lp
iizEtoNWTFYpgp3MuXYtfvr+6p6VdwZkZ5xTUebK4bIRdwKBgErJnqysNBPDEiKt
R6HoiCkIJ1jWgLEDCdw+2HLzLseHix8Zh5AmVs2yj3tdFDT8Pc+35epaXxx1+F0F
q9D317n42V7jN7/xpmbMnZh41F/KZr/ynOH3+EupKhPZTAYa1/nAgpqJfSKWrxTz
oIKnC8V0iiOwnhuzPJ5x7pi4n9VFAoGBAMV7OdzkXvb4WbatXJfxSWJI+kKosFyG
oKqnGYck2eErXerZuV6f1d/tN0zh4SbyDdGg2HeykIRrn9WWS2DRte1yqbkZzbRp
RxHdfk3+NYJ8V9mXxglPGUQkYFcuYFk/DDtwZ8wMwgBs/LpDt+dWU4kJfwlJ/nYb
BfnGddp/RH3/AoGAYxXvoxuhGzMXvDLNJ0SNuqNUfZ/F/ltMAcPmhtJkTo+RpZlm
eBvXrduLemNPYcNxTNmuRMgA4kVHOlu+/s7VQ4sRcNp7Fgau3+aqkE/9pkV3wJnf
xTlPlC4y+VeMKqBczpIXBD42mQMSwe9x/chOVQ+oebqB6Nvyk8RbcI9fJEs=
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PUBLIC KEY-----
CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjwkdyAvwfL6zI
r2O6MF2ipNd/pkkV+5+9wOyvAL9IHY4WRMmmLBGiBTj1Kln79ttChegxy/XME7ip
zt2KXq7qaMT7ZiscB0pPpLCpViueGxY90VbYmTeUrtvFJ+fJ5k4InuYtxJpwIpK0
zkTZEQbq7mjOOl0VaIzH4iBjKKDquYXxX5JSz5/9I2a4d5YvOoci703krFEAGw4F
snUR+NU0wKE2A66+t+xml3E6D/OoOowSzLk2o0vZOFqNG4/tas9HGKYO8ofmFYMh
bw5j/p3lZCHhPdklZZ4nlrEZIxPTlwdeY3qBG+7WyzctLbJLerg8cvwOJ5m46uQ4
f0j4mYf9AgMBAAE=
-----END RSA PUBLIC KEY-----
IPNS: QmTU9rhcwQM6refNwa64oqibG6C2mmFLhhxDBUjWDBtRa6
密钥是通过以下操作生成的:
ipfs key gen mykey --type=rsa --size=2048
其他语言的过程非常相似,例如 Node.js
我们希望允许用户根据他们维护的 IPFS 密钥名称从 IPNS 指针恢复他们的数据库。但是,由于 IPNS name/resolve
和 name/publish,
只有两个端点,因此似乎无法在不重新指向 IPNS 名称的情况下从密钥中派生出 IPNS 名称。可能吗?
我发现密钥都存在于 IPFS_HOME
内的 keystore
fodler 中,但我不确定这些文件的格式。这里的评论表明它们是 protobuf 格式,但我不确定如何从那里有意义地提取数据。
例如,使用 --decode-raw
给我这个:
root@ip-172-31-11-196:~# protoc --decode_raw $IPFS_HOME/keystore/keypairfile
1: 0
2: "02[=10=]43[=10=]2[=10=]1[=10=]0[=10=]22[=10=]1[=10=]1[=10=]036v\+s01`8Y4Y3I7h4746Q6W7ZA771\t4?7Y2tP175^465Q1*[n[=10=]4Lh76F05yr1337D~14j23I[5rv4641WO72+3|674z<~2K524664+3JE61\n2,n56544224>355l703\6~*h73177P2744W;54pE670\t7564\'K7E35c50102176340}2J47+[=10=]736704>[31Z71\'4_o77244F47431NM1404D*-Pa5%136H15[=10=]453Q27[=10=]707362{772421q6[=10=]022222I1[=10=]2[=10=]3[=10=]1[=10=]0[=10=]1[=10=]22[=10=]1[=10=]0[=10=]2[=10=]37061437[=10=]75C0[=10=]31\&870F{7l26g6d#Xd5UK<16721%061+jq[=10=]173Ht24&0R[=10=]1`422a66\'462T?Z04p4a0{7Y21k7?`+;265=F6wP[=10=]6F_t34m105 2Q47F/76V2836}97M225Z%5[=10=]7076L63%3160P5\t72326572W27e3k?[=10=]144k236W79800741Ft5427^6k-)]eD1[=10=]727-J1\cJh6205\t2Q\0107q\t60${25y06\r44P72DR7[=10=]160$202xp1217*09\t220[=10=]1[=10=]211[=10=]01p|566*3%460i3Y[=10=]217$2g7WT!C52n7`\r\t3(q33K26X3B17p\t74|+_73k05[=10=]0Fr3pqW[=10=]1>G31y3p751K2>3]Od55034577R4GA66W1@*s05`>}713PU2]56]=6n[=10=]56P7w32[=10=]1[=10=]211[=10=]01mfm9y631>4[=10=]7C040200731|W05w3~\'SD9r27;)06)[X<XH1a408o14[=10=]70162,0e[=10=]1m00246u177714]2~{o0h@0(-7FF01X0[=10=]1*\t60355461g>6525H3706522(615c0371[=10=]210O9A70h77124NYD5m2O0g3y434014!:47700460200I0XZ600`5]65420)474`;kH2600347576,7045c[=10=]56636*2426<39(4OF3172E)7O[35234W262044766K6[=10=]1[=10=]210370\"673y01=424bH\r>016->0712tH0zF4771P\r67?a4175530\r2[=10=]6*4]41i404&7 q76y55WG6[22M6ZR54171222370645*5&26706#6\".&163>410@66676,4z215k1[=10=]211[=10=]01135006026G151!533\7N2[=10=]44>4\nP65-0b\6=4C\t723xC7P3443Xn400A3[=10=]1N233r[=10=]46v0v\"g545[=10=]1L;4,426247Z25)244771[=10=]45(60115[=10=]215Y4Cb%2uB337-kr567777+02"
这似乎是两个二进制项,但我仍然无法完全从...中提取 IPNS 名称,或者是吗?
这是一个 Go 中的工作示例,说明如何读取 RSA 密钥对和 base58 编码 public 密钥以获取 IPNS 对等 ID:
package main
import (
"bufio"
"bytes"
"encoding/pem"
"fmt"
"log"
"github.com/ipfs/go-ipfs/keystore"
b58 "github.com/mr-tron/base58/base58"
mh "github.com/multiformats/go-multihash"
)
func main() {
ks, err := keystore.NewFSKeystore("/Users/username/.ipfs/keystore/")
if err != nil {
log.Fatal(err)
}
priv, err := ks.Get("mykey")
if err != nil {
log.Fatal(err)
}
privBytes, err := priv.Bytes()
if err != nil {
log.Fatal(err)
}
var privPEM bytes.Buffer
privWriter := bufio.NewWriter(&privPEM)
pem.Encode(privWriter, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privBytes,
})
privWriter.Flush()
pub := priv.GetPublic()
var pubPEM bytes.Buffer
pubBytes, err := pub.Bytes()
pubWriter := bufio.NewWriter(&pubPEM)
pem.Encode(pubWriter, &pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pubBytes,
})
pubWriter.Flush()
privPEMString := string(privPEM.Bytes())
pubPEMString := string(pubPEM.Bytes())
var alg uint64 = mh.SHA2_256
maxInlineKeyLength := 42
if len(pubBytes) <= maxInlineKeyLength {
alg = mh.ID
}
hash, _ := mh.Sum(pubBytes, alg, -1)
peerID := b58.Encode(hash)
fmt.Println(privPEMString)
fmt.Println(pubPEMString)
fmt.Println("IPNS:", peerID)
}
输出:
-----BEGIN RSA PRIVATE KEY-----
CAASpwkwggSjAgEAAoIBAQDjwkdyAvwfL6zIr2O6MF2ipNd/pkkV+5+9wOyvAL9I
HY4WRMmmLBGiBTj1Kln79ttChegxy/XME7ipzt2KXq7qaMT7ZiscB0pPpLCpViue
GxY90VbYmTeUrtvFJ+fJ5k4InuYtxJpwIpK0zkTZEQbq7mjOOl0VaIzH4iBjKKDq
uYXxX5JSz5/9I2a4d5YvOoci703krFEAGw4FsnUR+NU0wKE2A66+t+xml3E6D/Oo
OowSzLk2o0vZOFqNG4/tas9HGKYO8ofmFYMhbw5j/p3lZCHhPdklZZ4nlrEZIxPT
lwdeY3qBG+7WyzctLbJLerg8cvwOJ5m46uQ4f0j4mYf9AgMBAAECggEAQPhftxdA
4oiQCmN12FwJqebKDoDZ4mp4BAIvwjA9YI4FxTZ0K3Hwyb4hpFYjeyvNGinmtaXQ
BRovGEmJivo9fWLLpkdbztAJk7SQLI4HPT/O1W2ND5aNc116FcCvbznCUtU5Jh8q
SwihvvAEVcN0rLm7rfCaMwwy9KX9xSuG0830suMmVJ31W0evzRYHtnsvmDC9rdrA
TOy2HZdbL5Bty+nSwOlD608hCPWG6jCH5/BpEA3nCGX6KGH4yqFjaWGRA54cGGsh
bcKP1Hsdk0zle+Epl04yR1h2XCuwfmM3yegZuKjG5dfF51kV0yq2kND4F47D5azp
QJEhYHHOi6dvhQKBgQDwhZVl0W1rZjUvzkf/mZ2uC7aL64Rg1DFWNpSc05NK4IBS
eAf17HCCxLHCZnR0r8+CC0bOR+0xFT24RKcDyiPzpUo90LKHV3CXZEeFEWwfCg6N
RUfKMVLu9Vf5z7U4V2lOkojE7pWLt/ZMEAxXByQPlNyARfiRI8HPsPgrTlJvKwKB
gQDyam+oJbAfLvEFQ+h0B1ov3/3BEzV3GRkRz/IHTzQvHKyrN8zn/NZzQfrv3GR8
5W9BumpdfPkV5kCJb00fjS7AgLGWGHBsqzyDdliZdiQ5h5b15SflDrzfCF6c23lp
iizEtoNWTFYpgp3MuXYtfvr+6p6VdwZkZ5xTUebK4bIRdwKBgErJnqysNBPDEiKt
R6HoiCkIJ1jWgLEDCdw+2HLzLseHix8Zh5AmVs2yj3tdFDT8Pc+35epaXxx1+F0F
q9D317n42V7jN7/xpmbMnZh41F/KZr/ynOH3+EupKhPZTAYa1/nAgpqJfSKWrxTz
oIKnC8V0iiOwnhuzPJ5x7pi4n9VFAoGBAMV7OdzkXvb4WbatXJfxSWJI+kKosFyG
oKqnGYck2eErXerZuV6f1d/tN0zh4SbyDdGg2HeykIRrn9WWS2DRte1yqbkZzbRp
RxHdfk3+NYJ8V9mXxglPGUQkYFcuYFk/DDtwZ8wMwgBs/LpDt+dWU4kJfwlJ/nYb
BfnGddp/RH3/AoGAYxXvoxuhGzMXvDLNJ0SNuqNUfZ/F/ltMAcPmhtJkTo+RpZlm
eBvXrduLemNPYcNxTNmuRMgA4kVHOlu+/s7VQ4sRcNp7Fgau3+aqkE/9pkV3wJnf
xTlPlC4y+VeMKqBczpIXBD42mQMSwe9x/chOVQ+oebqB6Nvyk8RbcI9fJEs=
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PUBLIC KEY-----
CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjwkdyAvwfL6zI
r2O6MF2ipNd/pkkV+5+9wOyvAL9IHY4WRMmmLBGiBTj1Kln79ttChegxy/XME7ip
zt2KXq7qaMT7ZiscB0pPpLCpViueGxY90VbYmTeUrtvFJ+fJ5k4InuYtxJpwIpK0
zkTZEQbq7mjOOl0VaIzH4iBjKKDquYXxX5JSz5/9I2a4d5YvOoci703krFEAGw4F
snUR+NU0wKE2A66+t+xml3E6D/OoOowSzLk2o0vZOFqNG4/tas9HGKYO8ofmFYMh
bw5j/p3lZCHhPdklZZ4nlrEZIxPTlwdeY3qBG+7WyzctLbJLerg8cvwOJ5m46uQ4
f0j4mYf9AgMBAAE=
-----END RSA PUBLIC KEY-----
IPNS: QmTU9rhcwQM6refNwa64oqibG6C2mmFLhhxDBUjWDBtRa6
密钥是通过以下操作生成的:
ipfs key gen mykey --type=rsa --size=2048
其他语言的过程非常相似,例如 Node.js