The short go file at ipfs-key/main.go at master · whyrusleeping/ipfs-key · GitHub generates keypairs and prints the peer ID in the 12D3KooW…
format. I’d like to obtain the keys in the k51qzi5uqu5d… format.
I can obtain the k51… format using ipfs key import some-name private-key-file
followed by ipfs key list -l
, but I’m looking for a way to obtain the k51… in go, or at least without using an external process.
After a lot of searching, I found https://cid.ipfs.io/ which shows that, after decoding, that site shows some very similar info for the following two hashes (obtained using the standalone key generator and ipfs key import):
12D3KooWPVYKwhPsyD1kpaaVNvJoqd4tdZR4VgxVmo9NSzWVQjCj
k51qzi5uqu5dl8wlbw09j1cpr1i456yb3mv0r5wnpx3wz6qq8pnppkvgqdepc8
Once converted to CIDv1 base32, they become:
bafyaajaiaejcbszrcftl53w5t63k6tgiyk7uvrdr3to6pjy76azeib2h4ccm6dgi
bafzaajaiaejcbszrcftl53w5t63k6tgiyk7uvrdr3to6pjy76azeib2h4ccm6dgi
Aside from the bafy/bafz (which seems to indicate the codec 0x70 vs 0x72), there’s no difference.
I know how to convert the CIDv1 base32 bafy
or bafz
to a CIDv1 base36 k50 / k51 using ipfs cid format -b base36 baf…
, and from what I understand it’s a simple base conversion.
I’m still stumped about how I would get the CIDv1 base32 format from the 12D3KooW…
, it seems that the multicodec identifier 0x72 gets inserted somehow into the mix (because the 12D… hash has everything implicit) and there’s something related to protobuf, but I haven’t used that.
So I guess my question is, “how do I protobuf the multicodec :-p to get from 12D… to one of the CIDv1 encodings?”.
Thanks a lot
3 Likes
You’re right, CIDv0 are all-implicit, meaning CID begging with Q
or 1
(identity) will always be base58btc encoded.
In case of Q
CIDv0, the hash algorithm will be sha2-256, otherwise for 1
CIDv0, this is indeed an identity multihash.
So you can simply decode the entire 12D3KooWPVYKwhPsyD1kpaaVNvJoqd4tdZR4VgxVmo9NSzWVQjCj
as base58btc.
It will give you the following multihash (as hex): 002408011220CB311166BEEEDD9FB6AF4CC8C2BF4AC471DCDDE7A71FF032440747E084CF0CC8
We have:
-
00
for the hash function, here: identity
-
24
for the length in bytes (0x24 = 36 bytes = 288 bits) of the digest
- The following is the identity digest.
You can now create the new identity using the CIDv1 you want.
For instance, we’ll create the CIDv1 base36 you asked for:
First, we add the multicodec prefix libp2p-key
(0x72) and the CIDv1 prefix (0x01).
Then, we encode the whole 0172002408011220CB311166BEEEDD9FB6AF4CC8C2BF4AC471DCDDE7A71FF032440747E084CF0CC8
as base36.
We get this: 51qzi5uqu50cgk08ogw8k8ck8swgoo4kww0k08k4gscwcsccg4sscog0ssw0c
We add the k
base36 multibase-prefix, and we get:
k51qzi5uqu50cgk08ogw8k8ck8swgoo4kww0k08k4gscwcsccg4sscog0ssw0c
And there you go! (but you could also use the multibase/multihash/multicodec or CID lib).
(see GitHub - multiformats/cid: Self-describing content-addressed identifiers for distributed systems for more info)
3 Likes
Thanks a lot! Exactly what I was looking for and couldn’t infer by guesswork
1 Like
Were you able to get this to work in Go? Could you show how you did it? I am stuck on this same problem. Thanks!
EDIT* I was able to figure this out! Just sharing incase anyone else in the future sees this thread. First I create a keyencoder object and specify the k option:
keyEnc, err := ke.KeyEncoderFromString("k")
*Include ke "github.com/ipfs/go-ipfs/core/commands/keyencode"
in the imports section
Then after generating a ed25519 keypair using:
sk, pk, err := ic.GenerateKeyPair(ic.Ed25519, 256)
*Include ic "github.com/libp2p/go-libp2p-core/crypto"
in the imports section
I grab the peerID:
pidpk, err := peer.IDFromPublicKey(pk)
*include peer "github.com/libp2p/go-libp2p-core/peer"
in the imports section
I formated it using:
peerID := keyEnc.FormatID(pidpk)
Then when you print you will get 'k51…"
After going deep down this rabbit hole, still can’t figure out how to create the digest from a secp256k1 public key to use as the identity hash
.
I can see from importing the output ID generated from importing it into go-ipfs that it includes the public key, which is:
03E1DD7882E3AD98145004DF308C4F2E4C44845C56C91A9B300EB8144B33766DFB
So where does this preamble come from: 08021221
?
Got it.
Seriously though if there’s a function embedded in one of the many libraries that already deals with this conversion, someone give me a clue. If not, I’ll definitely submit a pull because going from a keypair to an IPNS subdomain addressable hash is super important.