Signed XID Documents
January 31, 2026 · View on GitHub
XID documents can be cryptographically signed to ensure their authenticity and integrity. When a XID document is signed, it is wrapped and a signature assertion is added. The signature can be verified to confirm that the document was signed by the holder of the inception key's private key.
Signing XID Documents
Most XID commands support a --sign option that allows you to sign the resulting XID document. The inception value signs the document with the XID's inception key.
Creating a Signed XID Document
When creating a new XID document from a private key, you can sign it immediately:
ALICE_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxdntswmjerdqdoxhnguzsdrhfcmjsfewkhkvezohkeycpasdysrvdgypeoemtgywztansgehdcxisespmvlhflnweksvyfnmhvofysnhyztpyhlftluweaoemenurstreckoybbfroektnncyls
envelope xid new $ALICE_PRVKEYS --nickname "Alice" --sign inception | envelope format
│ {
│ XID(93a4d4e7) [
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ {
│ 'privateKey': PrivateKeys(8624d38b, SigningPrivateKey(096547df, SchnorrPrivateKey(74343f20)), EncapsulationPrivateKey(d8e2032d, X25519PrivateKey(d8e2032d)))
│ } [
│ 'salt': Salt
│ ]
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ ]
│ } [
│ 'signed': Signature
│ ]
Note that the signed XID document has been wrapped (indicated by the outer { } braces), with the signature appearing as a 'signed': Signature assertion on the wrapped envelope.
Signing with Encrypted Private Keys
When using encrypted private keys, the encryption password is automatically used for signing:
ALICE_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxdntswmjerdqdoxhnguzsdrhfcmjsfewkhkvezohkeycpasdysrvdgypeoemtgywztansgehdcxisespmvlhflnweksvyfnmhvofysnhyztpyhlftluweaoemenurstreckoybbfroektnncyls
envelope xid new $ALICE_PRVKEYS --nickname "Alice" --private encrypt --encrypt-password "secret" --sign inception | envelope format
│ {
│ XID(93a4d4e7) [
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ {
│ 'privateKey': ENCRYPTED [
│ 'hasSecret': EncryptedKey(Argon2id)
│ ]
│ } [
│ 'salt': Salt
│ ]
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ ]
│ } [
│ 'signed': Signature
│ ]
Verifying Signed XID Documents
Most XID commands that accept a XID document also support a --verify option to verify the signature before processing. The inception value verifies that the signature was made with the inception key, which must be contained within the XID document.
Verifying with xid id
The xid id command can verify a signature when extracting the XID identifier:
ALICE_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxdntswmjerdqdoxhnguzsdrhfcmjsfewkhkvezohkeycpasdysrvdgypeoemtgywztansgehdcxisespmvlhflnweksvyfnmhvofysnhyztpyhlftluweaoemenurstreckoybbfroektnncyls
SIGNED_XID=`envelope xid new $ALICE_PRVKEYS --nickname "Alice" --sign inception`
envelope xid id --verify inception $SIGNED_XID
│ ur:xid/hdcxmuoxtyvddifztyryhymkgolbmefhssmejsgaykcljtjnfmaelrrkvwayehbzfesspmwerowy
If the XID document is not signed, verification fails:
ALICE_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxdntswmjerdqdoxhnguzsdrhfcmjsfewkhkvezohkeycpasdysrvdgypeoemtgywztansgehdcxisespmvlhflnweksvyfnmhvofysnhyztpyhlftluweaoemenurstreckoybbfroektnncyls
ALICE_PUBKEYS=`envelope generate pubkeys $ALICE_PRVKEYS`
UNSIGNED_XID=`envelope xid new $ALICE_PUBKEYS --nickname "Alice"`
envelope xid id --verify inception $UNSIGNED_XID
│ Error: envelope is not signed
Modifying Signed Documents
When modifying a signed XID document, you should verify the existing signature and re-sign after modification:
ALICE_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxdntswmjerdqdoxhnguzsdrhfcmjsfewkhkvezohkeycpasdysrvdgypeoemtgywztansgehdcxisespmvlhflnweksvyfnmhvofysnhyztpyhlftluweaoemenurstreckoybbfroektnncyls
BOB_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxhnlyeyzccpldfhsbmekkhspsmonlonctptenpkhettluhpzmteldssmejtdwbakttansgehdcxrkvapykpvalucwkgsalnmndefsfxfefsbwlujycebafybdqdpddwswswlktyzerfbeylotmk
BOB_PUBKEYS=`envelope generate pubkeys $BOB_PRVKEYS`
SIGNED_XID=`envelope xid new $ALICE_PRVKEYS --nickname "Alice" --sign inception`
envelope xid key add --nickname "Bob" $BOB_PUBKEYS $SIGNED_XID --verify inception --sign inception | envelope format
│ {
│ XID(93a4d4e7) [
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ {
│ 'privateKey': PrivateKeys(8624d38b, SigningPrivateKey(096547df, SchnorrPrivateKey(74343f20)), EncapsulationPrivateKey(d8e2032d, X25519PrivateKey(d8e2032d)))
│ } [
│ 'salt': Salt
│ ]
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ 'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│ 'allow': 'All'
│ 'nickname': "Bob"
│ ]
│ ]
│ } [
│ 'signed': Signature
│ ]
In this example:
--verify inceptionchecks that the incoming document is properly signed- The operation is performed (adding Bob's key)
--sign inceptioncreates a new signature for the modified document
Signature Options
The --sign and --verify options accept the following values:
none: (default) Do not sign or verifyinception: Sign with or verify using the XID's inception key
When using --sign inception, the inception key must be available in the XID document as a private key. If it is encrypted, the password used to encrypt it is also automatically used for signing.