Skip to content
42 changes: 32 additions & 10 deletions bip-0085.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -360,36 +360,58 @@ OUTPUT
* DERIVED ENTROPY=f7cfe56f63dca2490f65fcbf9ee63dcd85d18f751b6b5e1c1b8733af6459c904a75e82b4a22efff9b9e69de2144b293aa8714319a054b6cb55826a8e51425209
* DERIVED PWD=_s`{TW89)i4`

===RSA===
===GPG Keys===
Copy link
Contributor

Choose a reason for hiding this comment

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

Definitely need test vectors and expected outputs for all applications and sub applications. I can also add it to the reference implementation but won't be able to get to that right away. PRs welcome. https://github.com/akarve/bipsea

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm happy to work up some test vectors and a reference implementation once there is some agreement on a general direction :)


Application number: 828365'
Application number is dependant on the key type.
Copy link
Contributor

@akarve akarve Oct 6, 2025

Choose a reason for hiding this comment

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

I would recommend a single application number and then extend the path for different key types. That's more consistent with the rest of BIP85:

{same_app_number_for_all}/{key_type}/{key_bits}/{key_index}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would be the neatest solution


The derivation path format is: <code>m/83696968'/828365'/{key_bits}'/{key_index}'</code>
{|
!OpenGPG Key Type
!Application Number
|-
| RSA
| 828365'
|-
| ECC(Curve25519)
| 828366'
|-
Comment on lines +365 to +378
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The derivation path format already hardens the key_type component ("{key_type}'"), but the table also defines key_type values with a trailing apostrophe (e.g., "0'", "1'"). This is ambiguous and can lead to double-hardening / inconsistent interpretation across implementations. Define key_type as a plain integer (0..4) and state that the path component is always hardened, or remove the apostrophe from the path placeholder.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@copilot code review[agent] Can you add a note for the ECC key_types that mentions which key_bits lengths are valid

| ECC(secp256k1)
| 828367'
|-
| ECC(NIST)
| 828368'
|-
| ECC(Brainpool)
| 828369'
|-
|}

The RSA key generator should use BIP85-DRNG as the input RNG function.
The RSA key generator should use BIP85-DRNG as the input RNG function. Likewise, any ECC key types over 256bit should use BIP85-DRNG.

===RSA GPG===
====Primary Keys and Subkeys====

Keys allocated for RSA-GPG purposes use the following scheme:
Keys allocated for GPG purposes use the following scheme:

- Main key <code>m/83696968'/828365'/{key_bits}'/{key_index}'</code>
- Sub keys: <code>m/83696968'/828365'/{key_bits}'/{key_index}'/{sub_key}'</code>
- Primary key <code>m/83696968'/{key_type}'/{key_bits}'/{key_index}'</code>
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and elsewhere these list nested code blocks don't render as expected (... > View file)

Copy link
Contributor

Choose a reason for hiding this comment

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

In the description please motivate the need and intent of sub keys. It's not immediately obvious why this is needed above and beyond the standard key index.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's mostly about trying to follow the process elsewhere in BIP85 where a given derivation path will always map to a certain use case 1:1.

One solution to all of this is to basically just have BIP85 use the same derivation path for both primary keys and subkeys, regardless of the key algo being used.

- Sub keys: <code>m/83696968'/{key_type}'/{key_bits}'/{key_index}'/{sub_key}'</code>

- key_index is the parent key for CERTIFY capability
- sub_key <code>0'</code> is used as the ENCRYPTION key
- sub_key <code>1'</code> is used as the AUTHENTICATION key
- sub_key <code>2'</code> is usually used as SIGNATURE key

Note on timestamps:
Additional subkeys can be added to a primary key, including keys of a different key type, following the role pattern defined above, but the key_index MUST be incremented with each subkey.
Copy link
Contributor

@akarve akarve Oct 6, 2025

Choose a reason for hiding this comment

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

As for mixing types I would discourage that unless there's a really good reason. For one thing are we nesting derivation paths at that point? A worked example of mixed subkeys would help.

Copy link
Contributor

Choose a reason for hiding this comment

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

the use-case for this is basically scenarios where someone may want a strong and long-lived primary key that for their identity, but use different keys for the actual signing and stuff. (Whether due to limitations on smartcards, etc) For example, someone may have an ED25119 primary key and have subkeys use something like P256 or RSA subkeys for compatibility reasons.

reasonable enough. at that point why not turtles all the way down, e.g. the following or something like it?

{same_app_number_for_all}/
{key_type}/{key_bits}/key_index}/
{key_type}/{key_bits}/sub_key_index}/
...

Copy link
Contributor Author

@3rdIteration 3rdIteration Oct 6, 2025

Choose a reason for hiding this comment

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

the use-case for this is basically scenarios where someone may want a strong and long-lived primary key that for their identity, but use different keys for the actual signing and stuff. (Whether due to limitations on smartcards, etc) For example, someone may have an ED25119 primary key and have subkeys use something like P256 or RSA subkeys for compatibility reasons.

reasonable enough. at that point why not turtles all the way down, e.g. the following or something like it?

{same_app_number_for_all}/
{key_type}/{key_bits}/key_index}/
{key_type}/{key_bits}/sub_key_index}/
...

I think that would be a better approach overall, to have an app number to signify GPG keys generally and then an additional level of derivation for key type, but this would break compatibility with existing RSA implementations. (Even though it doesn't seem to me that there are any in the wild) The reality is that new key types will likely continue to be added to GPG, so the ability to add more in a neat way would be better long term. (With the rational for different applications for each key type being related to respecting the status of this BIP as 'Final')

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As for mixing types I would discourage that unless there's a really good reason. For one thing are we nesting derivation paths at that point? A worked example of mixed subkeys would help.

Even with that example, it's not really an issue to just assert that mixed key types are beyond the scope of the spec. (As most people will just use the same key type for everything)


<b>Note on timestamps:</b>

The resulting RSA key can be used to create a GPG key where the creation date MUST be fixed to unix Epoch timestamp 1231006505 (the Bitcoin genesis block time <code>'2009-01-03 18:05:05'</code> UTC) because the key fingerprint is affected by the creation date (Epoch timestamp 0 was not chosen because of legacy behavior in GNUPG implementations for older keys). Additionally, when importing sub-keys under a key in GNUPG, the system time must be frozen to the same timestamp before importing (e.g. by use of <code>faketime</code>).
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

This section now covers multiple GPG key types, but the timestamp note still refers specifically to "The resulting RSA key". Either generalize the statement to apply to all OpenPGP keys derived here (including ECC), or explicitly scope the timestamp requirement to RSA-only if ECC behavior differs.

Copilot uses AI. Check for mistakes.

Note on GPG key capabilities on smartcard/hardware devices:
<b>Note on GPG key capabilities on smartcard/hardware devices:</b>

GPG capable smart-cards SHOULD be loaded as follows: The encryption slot SHOULD be loaded with the ENCRYPTION capable key; the authentication slot SHOULD be loaded with the AUTHENTICATION capable key. The signature capable slot SHOULD be loaded with the SIGNATURE capable key.

However, depending on available slots on the smart-card, and preferred policy, the CERTIFY capable key MAY be flagged with CERTIFY and SIGNATURE capabilities and loaded into the SIGNATURE capable slot (for example where the smart-card has only three slots and the CERTIFY capability is required on the same card). In this case, the SIGNATURE capable sub-key would be disregarded because the CERTIFY capable key serves a dual purpose.


===DICE===

Application number: 89101'
Expand Down