XID Keys

January 31, 2026 · View on GitHub

envelope xid key --help

│ Work with a XID document's keys

│ Usage: envelope xid key <COMMAND>

│ Commands:
│   add     Add a key to the XID document
│   all     Retrieve all the XID document's keys
│   at      Retrieve the XID Document's key at the given index
│   count   Print the count of the XID document's keys
│   find    Find all XID keys matching the given criteria
│   remove  Remove the given key from the XID document
│   update  Updates the permissions, endpoints, or name of a key in a XID document
│   help    Print this message or the help of the given subcommand(s)

│ Options:
│   -h, --help     Print help
│   -V, --version  Print version

xid key add: Add a New Key to an Existing XID Document

All the same options as xid new are available. The same key may not be added twice.

XID_DOC=`envelope xid new --nickname 'Alice' $ALICE_PUBKEYS`

BOB_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxhnlyeyzccpldfhsbmekkhspsmonlonctptenpkhettluhpzmteldssmejtdwbakttansgehdcxrkvapykpvalucwkgsalnmndefsfxfefsbwlujycebafybdqdpddwswswlktyzerfbeylotmk
BOB_PUBKEYS=`envelope generate pubkeys $BOB_PRVKEYS`

envelope xid key add --nickname 'Bob' $BOB_PUBKEYS $XID_DOC | envelope format

│ XID(93a4d4e7) [
│     'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│         'allow': 'All'
│         'nickname': "Alice"
│     ]
│     'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│         'allow': 'All'
│         'nickname': "Bob"
│     ]
│ ]

xid key update: Update an Existing Key in an Existing XID Document

All the same options as xid new are available. The key must already exist in the XID document.

XID_DOC=`envelope xid new --nickname 'Alice' $ALICE_PUBKEYS | envelope xid key add --nickname 'Bob' $BOB_PUBKEYS`
envelope format $XID_DOC

│ XID(93a4d4e7) [
│     'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│         'allow': 'All'
│         'nickname': "Alice"
│     ]
│     'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│         'allow': 'All'
│         'nickname': "Bob"
│     ]
│ ]
XID_DOC_UPDATED=`envelope xid key update $BOB_PUBKEYS \
    --allow 'encrypt' \
    --allow 'sign' \
    $XID_DOC`
envelope format $XID_DOC_UPDATED

│ XID(93a4d4e7) [
│     'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│         'allow': 'All'
│         'nickname': "Alice"
│     ]
│     'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│         'allow': 'Encrypt'
│         'allow': 'Sign'
│         'nickname': "Bob"
│     ]
│ ]

xid key count: Count the Number of Keys in a XID Document

envelope xid key count $XID_DOC_UPDATED

│ 2

xid key at: Returns the Key at the Specified Index

The indexes are zero-based, and in the order the key assertions appear in the XID document's Gordian Envelope, which is not necessarily the order they appear via envelope format.

envelope xid key at 0 $XID_DOC_UPDATED | envelope format

│ PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│     'allow': 'All'
│     'nickname': "Alice"
│ ]
envelope xid key at 1 $XID_DOC_UPDATED | envelope format

│ PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│     'allow': 'Encrypt'
│     'allow': 'Sign'
│     'nickname': "Bob"
│ ]

xid key all: Returns All Keys in a XID Document

The keys envelopes separated by newlines.

envelope xid key all $XID_DOC_UPDATED

│ ur:envelope/lstpsotansgylftanshfhdcxrdhgfsfsfsosrloebgwmfrfhsnlskegsjydecawybniadyzovehncacnlbmdbesstansgrhdcxytgefrmnbzftltcmcnaspaimhftbjehlatjklkhktidrpmjobslewkfretcaetbnoycsfncsfgoycscstpsoihfpjziniaihqdkobsbw
│ ur:envelope/lrtpsotansgylftanshfhdcxndctnnflynethhhnwdkbhtehhdosmhgoclvefhjpehtaethkltsrmssnwfctfggdtansgrhdcxtipdbagmoertsklaflfhfewsptrlmhjpdeemkbdyktmtfwnninfrbnmwonetwpheoycsfncsfdoycsfncsgaoycscstpsoiafwjlidkpjkotey

Example capturing the above envelopes into a shell array. Note that newer shells like zsh use one-based indexing by default, but can be configured to use zero-based indexing.

XID_KEYS=($(envelope xid key all $XID_DOC_UPDATED))
envelope format ${XID_KEYS[1]}

│ PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│     'allow': 'All'
│     'nickname': "Alice"
│ ]
envelope format ${XID_KEYS[2]}

│ PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│     'allow': 'Encrypt'
│     'allow': 'Sign'
│     'nickname': "Bob"
│ ]

Retrieving Private Keys with --private

The key retrieval commands (xid key all, xid key at, xid key find) support a --private flag that returns the private key portion instead of the public key envelope. The behavior depends on whether the private key is encrypted and whether a password is provided.

For unencrypted private keys:

PRVKEY=`envelope generate prvkeys`
XID_UNENCRYPTED=`envelope xid new $PRVKEY --nickname "Bob"`
envelope xid key all --private $XID_UNENCRYPTED

│ ur:crypto-prvkeys/lftansgohdcxdlaojztijecphkdicstymeursboxiawllnmhbyynasjtcybdamisesasdmeniysptansgehdcxwdueglfycnynihpmdyimkksrcxenhtkgbaoylazcgalofwbzlfbgghjnvefmetehytaoynyt

The --private flag returns the raw ur:crypto-prvkeys UR, which can be used directly with other envelope commands that accept private keys.

For encrypted private keys without a password:

XID_ENCRYPTED=`envelope xid new $PRVKEY --private encrypt --encrypt-password "secret" --nickname "Alice"`
envelope xid key all --private $XID_ENCRYPTED | envelope format

│ ENCRYPTED [
│     'hasSecret': EncryptedKey(Argon2id)
│ ]

Without providing a password, the encrypted envelope is returned as-is. This allows you to verify that a key is encrypted without needing to decrypt it.

For encrypted private keys with the correct password:

envelope xid key all --private --password "secret" $XID_ENCRYPTED

│ ur:crypto-prvkeys/lftansgohdcxdlaojztijecphkdicstymeursboxiawllnmhbyynasjtcybdamisesasdmeniysptansgehdcxwdueglfycnynihpmdyimkksrcxenhtkgbaoylazcgalofwbzlfbgghjnvefmetehytaoynyt

With the correct password, the private key is decrypted and returned as the raw ur:crypto-prvkeys UR.

For encrypted private keys with an incorrect password:

envelope xid key all --private --password "wrong" $XID_ENCRYPTED

│ Error: invalid password

Providing an incorrect password results in an error.

For keys with no private key:

PUBKEYS=`envelope generate prvkeys | envelope generate pubkeys`
XID_NO_PRIVATE=`envelope xid new $PUBKEYS --nickname "Public Only"`
envelope xid key all --private $XID_NO_PRIVATE

│ Error: No private key present in this key

When a key was created from PublicKeys only (without a private key), attempting to retrieve the private key results in an error.

The --private flag works with all key retrieval commands:

# Get private key at index
envelope xid key at 0 --private --password "secret" $XID_ENCRYPTED

# Find inception key's private key
envelope xid key find inception --private --password "secret" $XID_ENCRYPTED

# Find key by name and get private key
envelope xid key find name Alice --private --password "secret" $XID_ENCRYPTED

# Find key by public key and get private key
envelope xid key find public $PUBKEYS --private --password "secret" $XID_ENCRYPTED

Note: Without the --private flag, key retrieval commands return the complete public key envelope, which includes public keys, metadata (nickname, endpoints, permissions), and the encrypted private key assertion (if present):

envelope xid key all $XID_ENCRYPTED | envelope format

│ PublicKeys(074761e6, SigningPublicKey(749b09a9, SchnorrPublicKey(cb62db34)), EncapsulationPublicKey(d9963678, X25519PublicKey(d9963678))) [
│     {
│         'privateKey': ENCRYPTED [
│             'hasSecret': EncryptedKey(Argon2id)
│         ]
│     } [
│         'salt': Salt
│     ]
│     'allow': 'All'
│     'nickname': "Alice"
│ ]

xid key find: Find a Key by the Given Criteria

xid key find public: Find a Key by the Given Public Key

Returns at most one key envelope.

envelope xid key find public $BOB_PUBKEYS $XID_DOC_UPDATED | envelope format

│ PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│     'allow': 'Encrypt'
│     'allow': 'Sign'
│     'nickname': "Bob"
│ ]

xid key find name: Find a Key by the Given Name

May return multiple key envelopes.

envelope xid key find name 'Alice' $XID_DOC_UPDATED | envelope format

│ PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│     'allow': 'All'
│     'nickname': "Alice"
│ ]
envelope xid key find name 'Wolf' $XID_DOC_UPDATED
(nothing returned)

xid key find inception: Find the Document's Inception Key

Returns at most one key envelope.

envelope xid key find inception $XID_DOC_UPDATED | envelope format

│ PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│     'allow': 'All'
│     'nickname': "Alice"
│ ]

xid key remove: Remove a Given Key

XID_DOC_REMOVED=`envelope xid key remove $ALICE_PUBKEYS $XID_DOC_UPDATED`
envelope format $XID_DOC_REMOVED

│ XID(93a4d4e7) [
│     'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│         'allow': 'Encrypt'
│         'allow': 'Sign'
│         'nickname': "Bob"
│     ]
│ ]
envelope xid key find inception $XID_DOC_REMOVED
(nothing returned)