Create an example of w3name using the HTTP API with Kubo CLI.
joshJarr opened this issue · 5 comments
We currently have little tangible documentation on how to use the w3name HTTP API in tandem with the Kubo CLI. This would be useful for builds that cannot use the Node client library.
Need to investigate whether this is a regular request & it warrants looking into.
There are a few options:
- Document how to successfully use & create a revision with the w3name API without the use of the JS Library, but through Kubo instead. This means explaining about serialising the CID, storing the private key locally, etc.
- Create a library in other languages, e.g. a Python library. But this would not 100% solve the issue of documenting the usage of this w3name API.
The five steps we currently use to explain this to users:
When creating a new record:
- Generate a key pair (we use libp2p-crypto to do this, but any way to make a Ed25519 pair will work). Sounds like you’ve done this!
- Next we need to create the IPNS entry, assigning the public key, IPFS content path, sequence number, and validity date. The client uses the IPNS package to do this on publish (see the JS client implementation for more on this) - sounds like you have done this too!
- Format the data: In the JS client, the entry is formatted and returned for us from the IPNS package (see IPNS.create). IPNS should return the entry for you in this format:
{
value: Uint8Array,
signature: Uint8Array,
validityType: 0,
validity: Uint8Array,
sequence: 2
}
- Now the data should be good, you’ll need to marshal the entry with proto buffer. in the JS client we use ipns.marshal.
- Finally you should be able to POST this entry to /name/{public_key} as a string, to do this stringify the marshalled entry to a base64paded string (see JS client for how we do this)
Let's start with updating the YAML file with all the necessary steps
https://web3.storage/docs/reference/w3name-http-api/
Testing manual IPNS creation with CLI tools:
Create a name and copy the outputted k5 key
ipfs key gen test
Export the private key to a file
ipfs key export --format pem-pkcs8-cleartext --output test.key test
Create an Protobuf definition ipns.proto
file with the following content
syntax = "proto2";
message IpnsEntry {
enum ValidityType {
// setting an EOL says "this record is valid until..."
EOL = 0;
}
// deserialized copy of data[value]
optional bytes value = 1;
// legacy field, verify 'signatureV2' instead
optional bytes signatureV1 = 2;
// deserialized copies of data[validityType] and data[validity]
optional ValidityType validityType = 3;
optional bytes validity = 4;
// deserialized copy of data[sequence]
optional uint64 sequence = 5;
// record TTL in nanoseconds, a deserialized copy of data[ttl]
optional uint64 ttl = 6;
// in order for nodes to properly validate a record upon receipt, they need the public
// key associated with it. For old RSA keys, its easiest if we just send this as part of
// the record itself. For newer Ed25519 keys, the public key can be embedded in the
// IPNS Name itself, making this field unnecessary.
optional bytes pubKey = 7;
// the signature of the IPNS record
optional bytes signatureV2 = 8;
// extensible record data in DAG-CBOR format
optional bytes data = 9;
}
Create a example.json
{
"value": "bafybeic7zrcqvhanfwl4o7ei3565o55ovu7bnrqdocumj6pg6s6dfskpvy",
"validity": "2023-01-01T00:00:00.000000001Z",
"validityType": 0,
"sequence": 1,
"ttl": 999
}
Install npm install cbor-cli
and protobuf
Serialize example.json
to CBOR
echo "69706e732d7369676e61747572653a"$(npx json2cbor example.json) > signatureV2
Sign, this is the value of signatureV2
openssl pkeyutl -sign -inkey test.key -rawin -in signatureV2 | openssl enc -base64
Create an example.data
file. The data field is the serialised CBOR from example.json
validity: "2023-01-01T00:00:00.000000001Z",
value: "bafybeic7zrcqvhanfwl4o7ei3565o55ovu7bnrqdocumj6pg6s6dfskpvy"
signatureV2: "NnxTpcQW94FMuDeRN088vmlewEw0kNGRHRydBEEft4VnIUMa/mB+2iaGjvUy4/1n\nYq86BxTAn4GL8U7qpzPzCA=="
sequence: 1
ttl: 999
pubKey: "k51qzi5uqu5dh4ui598wd8hnuqck51hoqld4ojqoq6j6keun25p6s2t7lro78a"
data: "69706e732d7369676e61747572653aa56576616c7565783b6261667962656963377a7263717668616e66776c346f376569333536356f35356f767537626e7271646f63756d6a3670673673366466736b7076796876616c6964697479781e323032332d30312d30315430303a30303a30302e3030303030303030315a6c76616c696469747954797065006873657175656e6365016374746c1903e7"
Encode example.data with ProtoBuf
cat example.data | protoc ipns.proto --encode=IpnsEntry | basenc --base64url > entry.serialised.base64
POST to w3name
curl -X POST --data '@entry.serialised.base64' https://name.web3.storage/name/k51qzi5uqu5dh4ui598wd8hnuqck51hoqld4ojqoq6j6keun25p6s2t7lro78a