Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions HIP-0013.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# HIP-0013: Profile Data and Wallet Addresses in TXT Records

```
Number: HIP-0013
Title: Profile Data and Wallet Addresses in TXT Records
Type: Standards
Status: Draft
Authors: @aoxborrow, @0xStefan, @Falci
Created: 2024-03-14
```

## Abstract

This document introduces IDNS (Identity-DNS), a standard for storing portable profile data and crypto wallet addresses securely within DNS TXT records.

## Motivation

Handshake holds significant potential for decentralized identity and wallet naming, but so far the focus has primarily been on websites. This proposal aims to establish a new and improved standard designed to encourage the development of decentralized identity applications for Handshake.

### Domains as Portable Identities
By attaching profile data such as a name, avatar, and bio, domains can act as portable online identities. This "bring-your-own-identity" approach, where users control their own data, has been adopted by platforms like [BlueSky](https://atproto.com/specs/handle), [Thunderbolt](https://www.spaceship.com/thunderbolt), and [Farcaster](https://docs.farcaster.xyz/learn/architecture/ens-names), which all utilize domains over traditional usernames.

Domains help overcome the scarcity of desirable namespace on social networks, allowing for more personalized and meaningful identifiers. For example, a proud Texan might choose `@richard.tx` over settling for `@richard_214`. Similarly, verified domains like `@nike.com` establish true authenticity, a clear advantage over fallible methods like blue checkmarks.

### Domains for Wallet Naming
In the same way that domains provide human-readable names for IP addresses, they can also map human-readable names to lengthy cryptocurrency addresses. Wallet naming makes it easy to send crypto to a friend or donate to a worthy cause. As crypto adoption grows, domains must evolve to support the payment rails of the future. Wallet naming continues to be the primary driver of adoption for blockchain naming systems like [ENS](https://docs.ens.domains/web/resolution).

### Advantages of TXT Records
Utilizing DNS offers practical benefits over blockchain-based systems:
* **Compatible** - Works with both Handshake and ICANN domains across different registrars and DNS providers.
* **Economical** - No gas fees needed for data storage or ongoing management.
* **Ease of Use** - Simple for both domain owners and developers. No specialized blockchain knowledge required.
* **Security** - DNSSEC ensures data integrity, while proven DNS infrastructure guarantees speed & availability.

### DNS: A Strategy for Adoption
This specification is fully compatible with ICANN domains, which dramatically broadens the potential user base. By growing the identity use-case for DNS domains, we can position Handshake as the superior alternative – private, decentralized, and censor-resistant. By building tools and services around IDNS that support both HNS and DNS domains, we can reach a much wider audience beyond the crypto community.

## TXT Specification

IDNS TXT records begin with **`IDNS1`** (version 1), and use the following format containing a record type, key, and value:

<pre><code><b>IDNS1 &lt;type&gt;:&lt;key&gt;=&lt;value&gt;</b>
</code></pre>

IDNS TXT records can contain one or more records in key=value pairs, separated by spaces:
<pre><code><b>IDNS1</b> profile:avatar=<ins>http://pic.com/me.png</ins> service:com.twitter=<ins>aoxborrow</ins>
</code></pre>

Records that contain spaces must be single quoted. Single quotes in the record can be escaped with a backslash:
Comment thread
aoxborrow marked this conversation as resolved.
Outdated
<pre><code><b>IDNS1</b> profile:location=<ins>'Berkeley, CA'</ins> profile:bio=<ins>'I\'m a passionate advocate for domain innovation.'</ins></code></pre>

### Profile Records (`profile`)
Human-readable user profile text data.
- **`<key>`** The profile record name, any text key is valid, no spaces.
- **`<value>`** The profile record data.
<pre><code><b>IDNS1 profile:&lt;key&gt;=&lt;value&gt;</b>

<i>Examples:</i>
IDNS1 profile:name=aox
IDNS1 profile:avatar=https://hns.id/domain/aox.hns/avatar.png
IDNS1 profile:location='Berkeley, CA'
IDNS1 profile:email=hey@me.com
</code></pre>

### Service Records (`service`)
Service keys must be made up of a reverse dot notation for a namespace which the service owns, for example, DNS names (e.g. .com, .io) or HNS name (i.e. .hns). Service Keys must contain at least one dot. See [EIP-634](https://eips.ethereum.org/EIPS/eip-634#service-keys).
- **`<key>`** A service key associated with the user, e.g. `com.github`.
- **`<identifier>`** Identifier for the service, e.g. Github username.
<pre><code><b>IDNS1 service:&lt;key&gt;=&lt;identifier&gt;</b>

<i>Examples:</i>
IDNS1 service:com.twitter=aoxborrow
IDNS1 service:com.github=0xstefan
IDNS1 service:io.keybase=pinheadmz
Comment thread
aoxborrow marked this conversation as resolved.
</code></pre>

### Wallet Records (`wallet`)
Cryptocurrency wallet addresses. Uses [SLIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) to specify different blockchains.
- **`<cointype>`** The type of cryptocurrency, using SLIP44 cointype symbol or number, e.g. `hns` or `5353`
- **`<address>`** Wallet address for the specific cryptocurrency.
<pre><code><b>IDNS1 wallet:&lt;cointype&gt;=&lt;address&gt;</b>

<i>Examples:</i>
IDNS1 wallet:btc=1Dvf5aQkVrVJeasRUDiLATGWLBGFWA9ovY
IDNS1 wallet:hns=hs1qshuyulxra3pqpwr40303t8pn79232zztuk4qgz
IDNS1 wallet:5353=hs1qshuyulxra3pqpwr40303t8pn79232zztuk4qgz
IDNS1 wallet:eth=0xa08abA528da538cd3547a73C93d51B90201294B6
Comment thread
aoxborrow marked this conversation as resolved.
Outdated
</code></pre>


### Contenthash Records (`contenthash`)
A content hash or address for distributed networks like IPFS. See [ENSIP-7](https://docs.ens.domains/ensip/7).
- **`<protocol>`** Distributed network protocol name, e.g. `ipfs`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading ENSIP-7 for the first time and it looks like the contenthash itself includes the protocol (the first few bits). Do we need to repeat it in plain text?

The value returned by contenthash MUST be represented as a machine-readable multicodec. The format is specified as follows:

<protoCode uvarint><value []byte>
protoCodes and their meanings are specified in the multiformats/multicodec repository.

The encoding of the value depends on the content type specified by the protoCode. Values with protocodes of 0xe3 and 0xe4 represent IPFS and Swarm content;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't worked with contenthash much but the idea was just to put something human readable, and basically a placeholder, since otherwise this record type has no key/param

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put a note that the <protocol> key is not used for resolution. I think it's kind of nice for human eyes but we could remove the key entirely

@pcfreak30 do you know if ENSIP-7 mulicodec is widely adopted? do you know of any reason not to use it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^^ @hodlthedoor same question

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to bring it up since it can save a few bytes on chain, but no strong opinions either way.
If the protocol is removed, it would look like (taking IPFS example from ENSIP-7):

IDNS1 contenthash:ipfs=0xe3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f

And the 0xe3 prefix indicates IPFS. So instead of matching txt.startsWith("ipfs="), it becomes txt.startsWith("0xe3").

But reading more of that proposal, since we are dealing with TXT records here, the multicodec hex is being saved as a string, which only makes it longer and take up more space! Simple text format (again example taken from ENSIP-7) is a lot shorter:

IDNS1 contenthash:ipfs://QmRAQB6YaCyidP37UdDnjFY5vQuiBrcqdyoW1CuDgwxkD4

hex would make sense if we are writing the bytes directly like a new record type IDNS1, but since TXT is string only, imo the text form is clearer and shorter.


Regardless of what's decided above, I think we should use real examples, at least of the same length as what will be expected.

- **`<address>`** Content address or content hash for distributed network.
<pre><code><b>IDNS1 contenthash:&lt;protocol&gt;=&lt;address&gt;</b>

<i>Examples:</i>
IDNS1 contenthash:ipfs=c04dfad360be65ba134aab7d07ec59f0547a73ef3168
IDNS1 contenthash:swarm=d191eb26786769f580809256b4685ef316805265ea1
</code></pre>


### Auth Records (`auth`)
Authentication provider for use with "Login with Domain." See [Handshake Login](https://learn.namebase.io/development/guides/handshake-login/using-handshake-login#set-up-a-custom-identity-manager). (WIP)
- **`<provider>`** Identity provider URL.
- **`<fingerprint>`** Provider-specific fingerprint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the WIP tag, but to add my 2¢ I hope this fingerprint part can be a bit more flexible. By only specifying the hash, we're locking into a single digest algo forever. I remember chatting with nb folks when they launched Handshake Login, but sadly don't have that history anymore.

Current nb's standard also includes a prefix/deviceId (source):

{prefix}._auth.{name}    TXT    v={x};fingerprint={hash};

And https://id.htools.work/ extends on that to support WebAuthn (security keys), etc. while being backward compatible like:

{prefix}._auth.{name}    TXT    v={x};fingerprint={hash};keyId={keyid};pubKey={pubkey}

example live record:

6bb41cddff1861dd._auth.noodleai. 5 IN	TXT	"v=0;fingerprint=efdaab62cdcd698f8d9a3c862ef431eb4085242d8fb4ac2e9ca1ebbdee2f4e74;keyId=TvCvFOBa5T2cAjgE380NjlDRW38RLuOP20XvL0csB8epbwnoyFzSlWG8y22Lx7cuDhqIeE8MDG2rFOShdRdSPw;pubKey=MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2uj6y+wk4MjYbloWg1X+GatakxVJGH9UtRKbEP" "Tey5luedoPtHnJhTP4rpfpvE4odF0GszyF7exJ4hqcIT5itg"

tl;dr: some flexibilty for future changes with hash algos, extra fields and versioning would be nice.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having flexibility on hash algos, and future proofing (quantum) is needed as well (not a nice to have).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rithvikvibhu @jeefave is our guy who did the original NB OIDC. would be very open to contribution from either of you. what is the purpose for using the device/prefix as the subdomain host, and could it be moved to part of the TXT if there is room? e.g.
HDNS1 auth:device={prefix} auth:fingerprint={hash} auth:keyid={keyid} auth:pubkey={pubkey}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc the idea behind the prefix was that since DNS doesn't* give you ALL records at once, adding a long enough pseudo-random prefix would mean nobody could enumerate find a list of all your devices. So if your laptop and phone stores keys, nobody can find the 2 records except the devices themselves since they store the device id locally in the browser.

When putting it on chain, it doesn't make a lot of sense since all records are already visible. So we do lose some privacy. Need to think about the format a bit more and honestly I don't really remember much about the protocol. btw hey John, been a while!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the initial NB OIDC protocol definition contains a prevision to customize the hash algos (here). In the context of OAuth, the underlaying OIDC server will need to cater for the desired algorithms (currently it is hardcoded). It could be useful to explore how this could be extended to allow signing with metamask or others.

The TXT format was inspired by these ietf drafts (1 and 2) where tag=value are separated by ";" and where values can be either text or base64 encoded strings depending on the nature of the tag.

I can confirm that the {prefix} subdomain aims to keep the list of the devices private because at the moment each devices generate their own private key. It seems like you remember quite well @rithvikvibhu :). Some similar mechanism could be leveraged to hide the list of services and profile infos if there are any privacy or security concerns? Another consideration is that using subdomains provides an elegant way to partition the data. It would mandate using DNSSEC. What are the benefits to store these data on chain?

What are your thoughts regarding this format?

<typehash>._hdns.<name> TXT <key>=<value>
servicehash1._hdns.name TXT v=0;identifier=aoxborrow
servicehash2._hdns.name TXT v=0;identifier=aoxborrow;picture=aHR0cHM6Ly9lbmNyeXB0ZWQtdGJuMC5nc3RhdGljLmNvbS9pbWFnZXM/cT10Ym46QU5kOUdjU1lzY2ZVQlVicXdHZF9ESFZoRy1aakNPRDdNVXB4cDR1aE5lN3RvVWc0dWcmcw==

Currently the HIP allows to define multiple provider fingerprints but the handshake login protocol sets the private key provider (idmanager) as a 1-1 association with its identity/domain. Relying parties are unaware of the signing party so identities can delegate to their preferred implementation. What use cases would require multiple id managers and how would they be resolved by the authication party?

image

<pre><code><b>IDNS1 auth:&lt;provider&gt;=&lt;fingerprint&gt;</b>

<i>Examples:</i>
IDNS1 auth:id.namebase.io=b9feeee2b4ad5c04dfad360be65ba134aab7d
IDNS1 auth:auth.varo.domains=6786769f580809256b4685ef316805265ea1e
</code></pre>

### TTL & Caching
Applications should respect the `ttl` setting of IDNS TXT records and cache the record data accordingly. Most profile records should have a long TTL, at least one hour (`3600`) or more. For wallet records, in order to replicate the behavior of a [HIP-2 server](https://github.com/pinheadmz/hip2-server), use a short TTL and rotate the wallet addresses frequently.

### TLD Records & DNSSEC
Handshake TLDs are encouraged to put IDNS TXT records directly onchain for the bare TLD. If using delegation (nameservers), DNSSEC is required. DNSSEC is required for all ICANN domains. A resolver may choose to support only `profile` and `service` records for ICANN TLDs that do not support DNSSEC.
Comment thread
aoxborrow marked this conversation as resolved.
Outdated


## References
* Stefan's Original HIP-0013 - TXT Record Naming Standards https://github.com/handshake-org/HIPs/pull/46
* EIP-634: Storage of text records in ENS https://eips.ethereum.org/EIPS/eip-634
* RFC 1464 https://datatracker.ietf.org/doc/html/rfc1464
* Handshake OIDC Authentication https://learn.namebase.io/development/guides/handshake-login/handshake-based-oidc-authentication-protocol
* James Stevens' Wallet IDs in DNS https://github.com/james-stevens/wallet-ids-in-dns
* A proposal for cryptocurrency addresses in DNS https://ma.ttias.be/proposal-cryptocurrency-addresses-dns
* Simplifying Bitcoin Addresses Using DNS https://bitcoinmagazine.com/technical/simplifying-bitcoin-addresses-dns
* OpenAlias https://openalias.org
* DNSLink https://dnslink.dev