From 3cc6bfc542271bbe4a057cb9d7a924dce9482702 Mon Sep 17 00:00:00 2001 From: pasta Date: Fri, 18 Sep 2026 13:54:29 -0500 Subject: [PATCH 1/3] docs(dip13): add application session authentication and application encryption sub-features Registers identity sub-features 6' (per-login session authentication keys) and 7' (per-contract application encryption keys), both with DIP-14 256-bit hardened leaves keyed by the identity id and by a request id or bound data contract id, so that wallets derive them without wallet-local indices. Updates the DIP-9 feature 5' assignment row. Co-Authored-By: Claude Fable 5.1 --- dip-0009/assignments.md | 2 +- dip-0013.md | 71 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/dip-0009/assignments.md b/dip-0009/assignments.md index 8e893002..b2b328e0 100644 --- a/dip-0009/assignments.md +++ b/dip-0009/assignments.md @@ -6,7 +6,7 @@ Here is a table of current feature paths and any associated DIP. Future DIPs may | ------------------ | ------------ | ------------------- | ---- | | `3'` | Masternode Keys | [DIP 0003: Deterministic Masternode List](https://github.com/dashpay/dips/blob/master/dip-0003.md) | The masternode related keys are located in the following sub-paths:
`0'/*` - _Reserved_
`1'/*` - Voting Key
`2'/*` - Owner Key
`3'/*` - Operator Key
`4'/*` - [Platform P2P Key](../dip-0028.md#calculating-the-platform-node-id) (ED25519)

For example, the first voting key for Dash would be at `m/9'/5'/3'/1'/0` | | `4'` | CoinJoin Keys | CoinJoin | The masternode related keys are located in the following sub-paths:
`0'/0/*` - Account 0 (external)
`0'/1/*` - Account 0 (change, not typically used)

For example, the first key of Account 0 for CoinJoin would be at `m/9'/5'/4'/0'/0/0`.

The main purpose of this using this path is to segregate CoinJoin-related keys from the BIP44 paths that are used to receive coins and change. CoinJoin derivation paths may require different lookup or gap values than the BIP44 paths that have much less transaction activity. Additionally, it may be possible to prune used keys from the BIP37 bloom filters used by mobile apps.| -| `5'` | Identity Keys | [DIP 0013: Identities in Hierarchical Deterministic wallets](../dip-0013.md) | The related keys are located in the following sub-paths:
`0'/key type'/identity index'/key index'` - Identity Authentication ([details](../dip-0013.md#identity-authentication-keys))
    Key types:
    `0'` - ECDSA (secp256k1)
    `1'` - BLS (bls12381)
`1'/*` - Identity Registration Asset Lock Funding ([details](../dip-0013.md#identity-registration-funding-keys))
`2'/*` - Identity Top up Asset Lock Funding ([details](../dip-0013.md#identity-top-up-funding-keys))
    `2'/funding index` - Not bound to a specific identity
    `2'/registration index'/top up index` - Bound to a specific identity
`3'/*` - Identity Invitation Asset Lock Funding ([details](../dip-0013.md#identity-invitation-funding-keys))
`4'/*` - Asset Lock Address Top up Funding
`5'/*` - Asset Lock Shielded Address Top up Funding

For example, the first ECDSA authentication key for the first identity on Dash would be at `m/9'/5'/5'/0'/0'/0'/0'`
The first Identity Registration Asset Lock Funding key for Dash would be at `m/9'/5'/5'/1'/0` | +| `5'` | Identity Keys | [DIP 0013: Identities in Hierarchical Deterministic wallets](../dip-0013.md) | The related keys are located in the following sub-paths:
`0'/key type'/identity index'/key index'` - Identity Authentication ([details](../dip-0013.md#identity-authentication-keys))
    Key types:
    `0'` - ECDSA (secp256k1)
    `1'` - BLS (bls12381)
`1'/*` - Identity Registration Asset Lock Funding ([details](../dip-0013.md#identity-registration-funding-keys))
`2'/*` - Identity Top up Asset Lock Funding ([details](../dip-0013.md#identity-top-up-funding-keys))
    `2'/funding index` - Not bound to a specific identity
    `2'/registration index'/top up index` - Bound to a specific identity
`3'/*` - Identity Invitation Asset Lock Funding ([details](../dip-0013.md#identity-invitation-funding-keys))
`4'/*` - Asset Lock Address Top up Funding
`5'/*` - Asset Lock Shielded Address Top up Funding
`6'/key type'/identity id'/request id'` - Application Session Authentication ([details](../dip-0013.md#application-session-authentication-keys))
    `identity id'` and `request id'` are 256-bit hardened children ([DIP 0014](../dip-0014.md))
`7'/key type'/identity id'/contract id'/key purpose'` - Application Encryption ([details](../dip-0013.md#application-encryption-keys))
    `identity id'` and `contract id'` are 256-bit hardened children ([DIP 0014](../dip-0014.md))
    Key purposes:
    `1'` - ENCRYPTION
    `2'` - DECRYPTION

For example, the first ECDSA authentication key for the first identity on Dash would be at `m/9'/5'/5'/0'/0'/0'/0'`
The first Identity Registration Asset Lock Funding key for Dash would be at `m/9'/5'/5'/1'/0` | | `15'` | DashPay - Incoming Funds | [DIP 0015: DashPay](../dip-0015.md#dashpay-incoming-funds-derivation-path) | The related keys are located in the following sub-paths: `/0'/account'/*`

For example, incoming funds for the first identity would be at `m/9'/5'/15'/0'/*` | | `16'` | DashPay - Auto Accept Proof | [DIP 0015: DashPay](../dip-0015.md#auto-accept-proof-autoacceptproof) | The related keys are located in the following sub-paths: `16'/expiration timestamp'`

For example, the key for a proof expiring at a Unix epoch time of `1605927033` would be at `m/9'/5'/16'/1605927033'` | | `17'` | Platform Payment Addresses | [DIP 0017: Dash Platform Payment Addresses and HD Derivation](../dip-0017.md) | The related keys are located in the following sub-paths: `17'/key_class'/index` (default key_class' = `0'`) | diff --git a/dip-0013.md b/dip-0013.md index e5c6349d..a4e7f01e 100644 --- a/dip-0013.md +++ b/dip-0013.md @@ -21,6 +21,8 @@ 1. [Identity Registration Funding keys](#identity-registration-funding-keys) 1. [Identity Top Up Funding keys](#identity-top-up-funding-keys) 1. [Identity Invitation Funding keys](#identity-invitation-funding-keys) +1. [Application Session Authentication keys](#application-session-authentication-keys) +1. [Application Encryption keys](#application-encryption-keys) 1. [Copyright](#copyright) # Abstract @@ -196,6 +198,75 @@ It is recommended that 30 address hashes of these keys be added to the bloom fil If transactions containing 25 address hashes or more have been found, the filter should be regenerated with 30 more. +# Application Session Authentication keys + +Application Session Authentication keys are the seventh sub-feature for identities. They are +short-lived authentication keys a wallet registers on an identity on behalf of an external +application, so that the application can sign within the scope and lifetime the wallet has fixed +on the identity and never holds a key the wallet cannot expire or disable. Each key is meant to be +registered with an expiry and whatever bounds the wallet grants, and to be replaced rather than +reused. + +We define the following levels for them: + +`m / purpose' / coin_type' / feature' / sub feature' / key type' / identity id' / request id'` + +Sub feature is set to `6'`. + +Key type uses the same values as identity authentication keys (`0'` ECDSA, `1'` BLS). + +The last two levels are 256-bit hardened children as defined in +[DIP14 (Extended Key Derivation using 256-Bit Unsigned Integers)](./dip-0014.md): + +* `identity id'` is the 32-byte unique identifier of the identity the key is registered on, + interpreted as a 256-bit unsigned integer. Using the identity's own identifier rather than a + wallet-local identity index means the same seed derives the same key in any wallet, regardless + of the order in which that wallet discovered its identities. +* `request id'` is a 256-bit value unique to one application login request. It is recommended to + be two rounds of SHA256 over the request public key, where the request public key is the + ephemeral key the application presented when requesting access. Every login then derives a + distinct key, while a repeated request derives the same key and can be recognised as a repeat. + +Keys on this path are not expected to be recovered from seed. Their public halves and their +lifetime are recorded on the identity, and once expired or disabled they are never needed again. +Wallets should not scan this path during identity recovery. + +# Application Encryption keys + +Application Encryption keys are the eighth sub-feature for identities. They are long-lived +encryption keys a wallet derives for one data contract and registers on the identity with contract +bounds naming that contract, so that content any application stores under that contract for the +identity can be decrypted in any wallet holding the seed. The key belongs to the contract whose +documents it protects, not to the application that requested it: any application the user +authorizes for that contract derives the same pair. + +We define the following levels for them: + +`m / purpose' / coin_type' / feature' / sub feature' / key type' / identity id' / contract id' / key purpose'` + +Sub feature is set to `7'`. + +Key type uses the same values as identity authentication keys. + +The `identity id'` and `contract id'` levels are 256-bit hardened children as defined in +[DIP14 (Extended Key Derivation using 256-Bit Unsigned Integers)](./dip-0014.md): + +* `identity id'` is the 32-byte unique identifier of the identity, as above. +* `contract id'` is the 32-byte unique identifier of the data contract the key is bound to, + interpreted as a 256-bit unsigned integer. A key bound to a single document type of a contract + still uses the contract's identifier; the document type only narrows the bounds recorded on the + identity. + +`key purpose'` is the Dash Platform identity key purpose the derived key is registered with, as a +hardened 31-bit child: `1'` for an ENCRYPTION key and `2'` for a DECRYPTION key. Following the +DashPay convention, an identity holds both for each contract it uses: the ENCRYPTION key is the +half the identity uses when it is the sender of an encrypted message, and the DECRYPTION key is +the half other identities encrypt to it with. + +Because every level is a stable identifier, a wallet restored from seed re-derives the same key +without any locally stored state, and finds the registered public key on the identity by its +contract bounds. + # Copyright Copyright (c) 2020 Dash Core Group, Inc. [Licensed under the MIT From c2c2e4626f0ae40cf7413a4a4d9e07a106b843a0 Mon Sep 17 00:00:00 2001 From: pasta Date: Fri, 18 Sep 2026 17:12:56 -0500 Subject: [PATCH 2/3] docs(dip13): fix the request public key encoding and the 256-bit byte order Co-Authored-By: Claude Fable 5.1 --- dip-0013.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dip-0013.md b/dip-0013.md index a4e7f01e..4d565e01 100644 --- a/dip-0013.md +++ b/dip-0013.md @@ -224,8 +224,12 @@ The last two levels are 256-bit hardened children as defined in of the order in which that wallet discovered its identities. * `request id'` is a 256-bit value unique to one application login request. It is recommended to be two rounds of SHA256 over the request public key, where the request public key is the - ephemeral key the application presented when requesting access. Every login then derives a - distinct key, while a repeated request derives the same key and can be recognised as a repeat. + ephemeral secp256k1 key the application presented when requesting access, in its 33-byte + compressed encoding. Every login then derives a distinct key, while a repeated request derives + the same key and can be recognised as a repeat. + +Wherever this document interprets 32 bytes as a 256-bit unsigned integer, the first byte is the +most significant, so the bytes are the integer's `ser256` form from DIP14. Keys on this path are not expected to be recovered from seed. Their public halves and their lifetime are recorded on the identity, and once expired or disabled they are never needed again. From ba2635d3fcfbdf2628c8556705be0bf42d627607 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 22 Sep 2026 23:54:08 -0500 Subject: [PATCH 3/3] docs(dip13): the application sub-features use the ECDSA key type only The identity, request and contract id levels are DIP-14 256-bit children, which DIP14 defines only for secp256k1 derivation, and the encryption pair is used for secp256k1 ECDH. Key type 1' (BLS) is therefore reserved on sub-features 6' and 7' rather than offered: a BLS deriver has no defined way to derive the 256-bit levels. Co-Authored-By: Claude Opus 5.5 (1M context) --- dip-0009/assignments.md | 2 +- dip-0013.md | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dip-0009/assignments.md b/dip-0009/assignments.md index b2b328e0..6f0cff8a 100644 --- a/dip-0009/assignments.md +++ b/dip-0009/assignments.md @@ -6,7 +6,7 @@ Here is a table of current feature paths and any associated DIP. Future DIPs may | ------------------ | ------------ | ------------------- | ---- | | `3'` | Masternode Keys | [DIP 0003: Deterministic Masternode List](https://github.com/dashpay/dips/blob/master/dip-0003.md) | The masternode related keys are located in the following sub-paths:
`0'/*` - _Reserved_
`1'/*` - Voting Key
`2'/*` - Owner Key
`3'/*` - Operator Key
`4'/*` - [Platform P2P Key](../dip-0028.md#calculating-the-platform-node-id) (ED25519)

For example, the first voting key for Dash would be at `m/9'/5'/3'/1'/0` | | `4'` | CoinJoin Keys | CoinJoin | The masternode related keys are located in the following sub-paths:
`0'/0/*` - Account 0 (external)
`0'/1/*` - Account 0 (change, not typically used)

For example, the first key of Account 0 for CoinJoin would be at `m/9'/5'/4'/0'/0/0`.

The main purpose of this using this path is to segregate CoinJoin-related keys from the BIP44 paths that are used to receive coins and change. CoinJoin derivation paths may require different lookup or gap values than the BIP44 paths that have much less transaction activity. Additionally, it may be possible to prune used keys from the BIP37 bloom filters used by mobile apps.| -| `5'` | Identity Keys | [DIP 0013: Identities in Hierarchical Deterministic wallets](../dip-0013.md) | The related keys are located in the following sub-paths:
`0'/key type'/identity index'/key index'` - Identity Authentication ([details](../dip-0013.md#identity-authentication-keys))
    Key types:
    `0'` - ECDSA (secp256k1)
    `1'` - BLS (bls12381)
`1'/*` - Identity Registration Asset Lock Funding ([details](../dip-0013.md#identity-registration-funding-keys))
`2'/*` - Identity Top up Asset Lock Funding ([details](../dip-0013.md#identity-top-up-funding-keys))
    `2'/funding index` - Not bound to a specific identity
    `2'/registration index'/top up index` - Bound to a specific identity
`3'/*` - Identity Invitation Asset Lock Funding ([details](../dip-0013.md#identity-invitation-funding-keys))
`4'/*` - Asset Lock Address Top up Funding
`5'/*` - Asset Lock Shielded Address Top up Funding
`6'/key type'/identity id'/request id'` - Application Session Authentication ([details](../dip-0013.md#application-session-authentication-keys))
    `identity id'` and `request id'` are 256-bit hardened children ([DIP 0014](../dip-0014.md))
`7'/key type'/identity id'/contract id'/key purpose'` - Application Encryption ([details](../dip-0013.md#application-encryption-keys))
    `identity id'` and `contract id'` are 256-bit hardened children ([DIP 0014](../dip-0014.md))
    Key purposes:
    `1'` - ENCRYPTION
    `2'` - DECRYPTION

For example, the first ECDSA authentication key for the first identity on Dash would be at `m/9'/5'/5'/0'/0'/0'/0'`
The first Identity Registration Asset Lock Funding key for Dash would be at `m/9'/5'/5'/1'/0` | +| `5'` | Identity Keys | [DIP 0013: Identities in Hierarchical Deterministic wallets](../dip-0013.md) | The related keys are located in the following sub-paths:
`0'/key type'/identity index'/key index'` - Identity Authentication ([details](../dip-0013.md#identity-authentication-keys))
    Key types:
    `0'` - ECDSA (secp256k1)
    `1'` - BLS (bls12381)
`1'/*` - Identity Registration Asset Lock Funding ([details](../dip-0013.md#identity-registration-funding-keys))
`2'/*` - Identity Top up Asset Lock Funding ([details](../dip-0013.md#identity-top-up-funding-keys))
    `2'/funding index` - Not bound to a specific identity
    `2'/registration index'/top up index` - Bound to a specific identity
`3'/*` - Identity Invitation Asset Lock Funding ([details](../dip-0013.md#identity-invitation-funding-keys))
`4'/*` - Asset Lock Address Top up Funding
`5'/*` - Asset Lock Shielded Address Top up Funding
`6'/0'/identity id'/request id'` - Application Session Authentication ([details](../dip-0013.md#application-session-authentication-keys))
    `0'` is the ECDSA key type (`1'` BLS is reserved); `identity id'` and `request id'` are 256-bit hardened children ([DIP 0014](../dip-0014.md))
`7'/0'/identity id'/contract id'/key purpose'` - Application Encryption ([details](../dip-0013.md#application-encryption-keys))
    `0'` is the ECDSA key type (`1'` BLS is reserved); `identity id'` and `contract id'` are 256-bit hardened children ([DIP 0014](../dip-0014.md))
    Key purposes:
    `1'` - ENCRYPTION
    `2'` - DECRYPTION

For example, the first ECDSA authentication key for the first identity on Dash would be at `m/9'/5'/5'/0'/0'/0'/0'`
The first Identity Registration Asset Lock Funding key for Dash would be at `m/9'/5'/5'/1'/0` | | `15'` | DashPay - Incoming Funds | [DIP 0015: DashPay](../dip-0015.md#dashpay-incoming-funds-derivation-path) | The related keys are located in the following sub-paths: `/0'/account'/*`

For example, incoming funds for the first identity would be at `m/9'/5'/15'/0'/*` | | `16'` | DashPay - Auto Accept Proof | [DIP 0015: DashPay](../dip-0015.md#auto-accept-proof-autoacceptproof) | The related keys are located in the following sub-paths: `16'/expiration timestamp'`

For example, the key for a proof expiring at a Unix epoch time of `1605927033` would be at `m/9'/5'/16'/1605927033'` | | `17'` | Platform Payment Addresses | [DIP 0017: Dash Platform Payment Addresses and HD Derivation](../dip-0017.md) | The related keys are located in the following sub-paths: `17'/key_class'/index` (default key_class' = `0'`) | diff --git a/dip-0013.md b/dip-0013.md index 4d565e01..15ad692f 100644 --- a/dip-0013.md +++ b/dip-0013.md @@ -213,7 +213,9 @@ We define the following levels for them: Sub feature is set to `6'`. -Key type uses the same values as identity authentication keys (`0'` ECDSA, `1'` BLS). +Key type is `0'` (ECDSA secp256k1). The next two levels are 256-bit children, which DIP14 defines +only for secp256k1 derivation, so `1'` (BLS) is reserved on this sub-feature and must not be +used. The last two levels are 256-bit hardened children as defined in [DIP14 (Extended Key Derivation using 256-Bit Unsigned Integers)](./dip-0014.md): @@ -250,7 +252,7 @@ We define the following levels for them: Sub feature is set to `7'`. -Key type uses the same values as identity authentication keys. +Key type is `0'` (ECDSA secp256k1), as above; `1'` is reserved. The keys are used for secp256k1 ECDH. The `identity id'` and `contract id'` levels are 256-bit hardened children as defined in [DIP14 (Extended Key Derivation using 256-Bit Unsigned Integers)](./dip-0014.md):