A protocol to store an encrypted private key for an HNS domain name in a TXT record
inside that that name's root zone resource. Users can access their domain
from any web browser (or nodejs console) using just the domain name and a strong
password. Once the key has been retrieved and decrypted client-side, the name's
root zone resource can be updated by creating an incomplete transaction
signed with SIGHASH_SINGLE | SIGHASH_ANYONECANPAY
. This allows a second party
(the server) to pay the fee for the UPDATE
and broadcast on behalf of the user.
The encryption currently relies on 10,000,000 iterations of PBKDF2 with a 128-bit salt and SHA256 PRF. Passwords should be at least 20 characters. Decryption takes about 10 seconds in Firefox and about 5 seconds in nodejs.
- User generates a 24-word mnemonic seed phrase.
- This can be generated by the app or by external process and pasted into the app.
- User enters a strong password which is used to encrypt the seed phrase.
- The encrypted blob is serialized as a base64 string in a TXT record in HNS Resource format.
- The first receive address at index
0
is derived and output to the user.
- The app outputs HNS resource data as both JSON (to be used with
hsw-rpc sendupdate
and as a hex blob (for use with Namebase's "Advanced DNS" field). - This
UPDATE
must be confirmed in the HNS blockchain before continuing.
- User requests a transfer of the name to the address computed in step 1 from Namebase,
or completes the transfer manually with
hsd
.
The user can now update their root zone data from the webapp using only their domain name and password:
- Client requests
getnameresource
for their name from the server. The response is JSON and contains a TXT record with the encrypted mnemonic phrase (from step 2). - Client decrypts the mnemonic with the user's passphrase.
- Client adds additional TXT records to their name's HNS resource.
- Client requests from the server the current
owner
(UTXO) of their name. - Client constructs a 1-input, 1-output transaction with a new
UPDATE
covenant that contains the updated HNS resource and signs it using the decrypted private key and sighash flagsSINGLE | ANYONECANPAY
. - Client sends this partially-signed transaction to the server as a seriazlied hex string.
- Server adds an additional input and output to pay the fee for this transaction, signs it with
SIGHASH_ALL
and broadcasts.
git clone https://github.com/pinheadmz/pinkie
cd pinkie
npm i
The Pinkie Swear server requires a peer dependency of
hsd
. The hsd
library must be
available in global node_modules
on your system and it is assumed that an
hsd
full node is running with a sufficiently funded wallet. To configure a
Pinkie Swear for mainnet,
see this commit.
Additional hsd
wallet and full node configuration settings are documented
here and in the
API-docs.
The client code is written in the context of nodejs but can be compiled for the
browser using bpkg
(included as dependency). It can be compiled with or without
being minified/uglified for either smaller transport, or debugging. Paranoid users
should use the dev mode if they are worried about interference from the uglify plugin.
These commands compile the code from lib/
into a git-ignored file
html/js/hnswallet-browser.js
which is requested by the html page.
Either way, large modules from the hsd
library are included in the payload
for wallet structure, transaction primitives, and message signing and it is a large file.
# compact
npm run build
# debug / auditable
npm run build-dev
node bin/pinkie.js
This command will start the webserver (by default on regtest at http://127.0.0.1:8000)
that serves the client front-end and also communicates with the hsd
full node
on the back-end.
The wallet-interfacing server does not have any checks or rate-limits yet and overall security of the coinjoin protocol has not yet been audited.