[urn] Re: URN Namespace Registration for SAID (Self-Addres sing Identifiers)

Wenjing Chu <[email protected]> Thu, 29 Jan 2026 15:07:09 +0000
Newsgroups gmane.ietf.urn
Message-ID <BY5PR13MB3364D159F0C06A4600614386C29EA@BY5PR13MB3364.namprd13.prod.outlook.com>
Thank you again, Dale, and earlier Ted, for your very helpful comments.
Sorry for my delay in responding. I hope I captured all the information I received and edited the application to address them. If I missed anything still, please let me know - I promise to follow up a lot quicker than last time. Thank you!

The new application is here: https://github.com/trustoverip/kswg-said-urn-charter/blob/main/urn_application.txt

I’m also attaching a copy in this email.

Changes included:

  *
ANBF syntax updated to reflect its relationship with CESR code and encoding more accurately
  *
CESR encoding and the SAID derivation procedure summarized in the document
  *
Examples extended both in terms of data format examples and digest functions
  *
Added text for security and privacy considerations
  *
Interoperability section revised
  *
Other general improvements and edits etc.

Best regards,
Wenjing



From: Wenjing Chu <[email protected]>
Date: Friday, November 21, 2025 at 10:51 AM
To: Dale R. Worley <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>
Subject: Re: [urn] Re: URN Namespace Registration for SAID (Self-Addressing Identifiers)

Thank you, Dale! Received both of your emails. I will use this reply to keep the thread going.

I will probably need a few days to go over many points you raised here.

But first, thanks to the suggestions about the ABNF section. I was a bit reluctant as I was including that section in the first place, precisely because of the issues you raised here. It is not the ABNF in a typical sense but rather describing the effect of a SAID calculation. I agree that your suggestion is a good way to resolve this issue.

Will follow up with a revised registration request.

Best,
Wenjing


From: Dale R. Worley <[email protected]>
Date: Wednesday, November 19, 2025 at 7:26 PM
To: Wenjing Chu <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>, [email protected] <[email protected]>
Subject: Re: [urn] Re: URN Namespace Registration for SAID (Self-Addressing Identifiers)
My apologies for neglecting this registration request for far too long.

Reading the submitted registration again, and addressing points as I run
into them:

The "Purpose" section reads very well to me.

As I noted before, I think the "Syntax" section should emphasize the
ABNF (as that is unambiguous and universally understood) and treat the
text parts as explanation, annotation, etc. of the ABNF.

Note that as the ABNF is written, an SAID URN must start with one of
exactly nine prefixes:  E, F, G, H, I, 0D, 0E, 0F, 0G.  You comment that
it would be useful to allow extensibility.  As the ABNF is stated,
allowing other prefixes would require an amendment to the registration.
And clearly, adding a digest algorithm that has a different length
output would require revising the ABNF.  An alternative would be for the
registration to say that an SAID URN must start with a prefix listed in
Table [whatever] of the CESR specification and that it contains as many
base64urlsafe characters as needed to encode the algorithm's output.

Regarding the table in section 11.4.2 of the CESR specification, I found
it hard to read.  In particular, it seems to contain information for a
variety of different codes that have different uses, all listed as if
they're part of the same class of codes.  The classes that I could
identify include "Count Codes", "Universal Genus Version Codes",
"Universal Count Codes that allow genus/version override", "Genus
Specific Count Codes", "Operation Codes", "Primitive Matter Codes",
"Basic One Character Codes", "Basic Two Character Codes".  This is quite
confusing for the uninitiated; naively I would expect each class of code
to be in a separate table, headed by a short summary of what the class
of codes is for.  But if you want the URN specification to reference an
extensible list of prefixes in the table, it's not clear how you would
write text that specifies the subset of all those codes which are
intended to be valid prefixes for SAID URNs.

There is also an interesting point about extensibility:  One has to know
how to calculate the desired hash function to create a CESR object, and
thus its SAID URN.  But one does not need to understand the hash
function to catalog the fact that "object [whatever] is named by SAID
URN [whatever]".  It appears to me that given a CESR object, one can
extract its SAID from the object itself, even if one does not know how
to calculate/verify its SAID.  So applications that interpret SAID URNs
can be extensible to handle URNs naming hash functions that they
themselves do not understand.  This might be worth mentioning in the
registration, perhaps in the form "Applications that input SAID URNs
must be prepared to handle URNs generated using hash functions that they
do not understand."

    Examples:

      - `urn:said:E8wYuBjhslETYaLZcxMkWrhVbMcA8RS1pKYl7nJ77ntA`
      - `urn:said:EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ`

    The above examples are 44 characters long in text representation,
    where `E` indicates Blake3-256 digest and the remaining 43 characters
    encode 256 bit digest. Additional digest functions are listed in CESR
    2.0, Section 11.4.2.

As I noted before, it would be beneficial to add examples that use other
hashes, and in particular, one with a different hash length.

The sentence "Additional digest functions are listed ..." might be
misinterpreted to mean that all digest functions listed in 11.4.2 are
valid, whereas only 9 are.  I would say something like

    The one-char-code and two-char-code prefixes specify the digest
    algorithm used to generate the digest according to the table in CESR 2.0
    section 11.4.2.  In the above examples, the initial `E' indicates the
    Blake3-256 digest algorithm.  [similarly for other prefixes used in
    the examples]

It is not clear to me how much of the processing in CESR we would want
in the registration.  But it seems to me we want the "Assignment" section
to make the following points:

- We want to say that the SAID strings are *generated from* the digital
  assets that they describe.  This isn't exactly the same as
  "self-assigned" because whoever is doing the work doesn't get to
  *choose* what the SAID is; the SAID is determined by the asset.

    To illustrate, here is an example of how the derivation works (from
    CESR 2.0, Section 11.6):

    Suppose the initial value of Python dict data structure is as follows:
    {
        "said": "",
        "first": "Sue",
        "last": "Smith",
        "role": "Founder"
    }

- We need some clarity as to what sort of digital assets can have SAID
  strings.  The one example presented is a Python dict containing one
  member "said", whose value will ultimately be the SAID string.  But
  it's unclear what the class of assets is intended to be.  It seems
  likely that there are a variety of "formats" of asset but each format
  has a canonical place inside it into which the SAID string will be
  copied once it is computed. ... But we need the registration to
  clearly describe the class of resources which can be named with the
  URNs.

  Let me expand on that:  It needs to be clear what resource (or set of
  "equivalent" resources) each URN names.

- The description mentions "consistent serialization" several times, but
  most of them seem to me to add complexity without adding clarity.
  Clearly, if you're going to hash a data structure, you need some sort
  of consistent serialization, so the reader doesn't need to be told
  that.  But since the registration doesn't describe *what* the
  serialization scheme is, why mention it?

    If we choose the 44 CESR character Blake3-256 digest for SAID
    derivation and use JSON serialization, the first of the derivation
    procedure is to insert the `#` character in place of the future SAID
    string:
    {
        "said": "############################################",
        "first": "Sue",
        "last": "Smith",
        "role": "Founder"
    }

- For exactness, you want to say "insert a number of `#' characters in
  place of the future SAID string, where the number (44) is the sum of the
  length of the digest's prefix `E' (1) plus the number base64urlsafe
  characters that will be used to encode the digest (43)".

- BTW, if the digital asset is a "binary" object, is the SAID string
  inserted into it in the same way, that is, base64urlsafe encoded?  If
  it is inserted in binary, it's probably worth warning that for some
  assets, the SAID string inserted into the asset is different from the
  one in the URN.

    For consistent serialization, we remove all extra white space:
    {"said":"############################################","first":"Sue","last":"Smith","role":"Founder"}

- This is clear.  And it is an indirect reference to the fact that
  consistent serialization is needed and implies that the CESR standard
  tells how to do that.

    The URN for the above data representation is:
    `urn:said:EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ`

- I think you want some more detail:  The SAID string consists of the
  code for the digest algorithm, `E', followed by the base64urlsafe
  representation of the digest value of the serialization,
  `JymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJe'.

    The URN for the above data representation is:
    `urn:said:EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ`

    Now, the Python data structure may be updated to:
    {
        "said": "EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ",
        "first": "Sue",
        "last": "Smith",
        "role": "Founder"
    }

- This needs some more clarity.  As far as I can tell, the URN is for the
  *digital asset*, and the updated Python data structure is what the user
  thinks of -- and stores and transmits -- as the digital asset.  "the
  above data representation" seems to unnecessarily add complexity, as
  the URN is *for* the Python data structure.

    It is important to note that verification of SAID (therefore
    `urn:said`) must be performed on the consistent serialization format
    of the digital asset.

- This seems to be unnecessary.  Obviously, to verify an SAID, one needs
  to repeat the computation of it, and that has the same serialization
  requirements as the initial computation.

    In addition, the use of CESR encoding allows
    lossless transformation between binary and text domains. This property
    is useful in digital assets which may be most optimally represented in
    binary or serialization schemes such as CBOR.

It seems to me that this could be omitted.  As written, it's not clear
what it really means.  To make it clear, there would have to be some
background regarding what the "binary and text domains" are.  And there
is the implication that SAID is only applicable to digital assets which
somehow have both text and binary representations, which would need to
be part of the specification of what the applicable class of assets is.

    Adopters MAY consider narrowing selections of digest functions to
    reduce complexity and improve interoperability with some cost in
    flexibility.

This seems to me to be a bad idea.  There's no problem with an
application that can only *generate* one digest function.  But if an
application wishes to *verify* SAIDs, then if it does not compute all of
the specified digest functions, its interoperability is reduced.

Dale

_______________________________________________
urn mailing list -- [email protected]
To unsubscribe send an email to [email protected]
urn_application (1).txt (text/plain, 12.3 KB)
Namespace Registration for Self-Addressing Identifiers (SAID)

Namespace Identifier:  said

Version:  2

Date:  2026-01-27

Registrant: Sam Smith, Wenjing Chu, Carly Huitema
on behalf of ToIP (Trust over IP), a project of the Linux Foundation Decentralized Trust
https://trustoverip.org/
Contact email: (Wenjing Chu) [email protected]

Purpose: 

Self-Addressing Identifiers (SAIDs) are self-referential content-addressable identifiers based on Composable Event Streaming Representation (CESR) [1] encoded cryptographic digest. This proposal defines a method to unambiguously identify digital assets that contain their SAIDs via their SAID identifiers in the urn:said namespace. Such urn:said identifiers can ease the ways of adopting SAIDs anywhere URNs are accepted and improve interoperability. These URNs are typically non-resolvable, serving as unique identifiers. However, optional mechanisms could be introduced in the future in addressing such requirements.

Syntax:

A `said` URN shall consist of two mandatory components in the following order, with `:` characters between each section.
 
  - URN identifier (`urn:said`): REQUIRED

  - SAID, in string representation as per Composable Event Streaming Representation (CESR) [1], Section 11.6 and represented with Base64URLSafe alphabet of RFC 4648 (with the exception of `=` pad character which is not used in CESR). REQUIRED

The ABNF of an `said` URN MUST be as follows:

```ABNF
said-urn = "urn:said:" said

said = cesr-code cesr-digest-value

cesr-code = <CESR type code identifying the digest algorithm>

cesr-digest-value = <Base64URLSafe encoded digest, length determined by cesr-code>

; Base64URLSafe characters (RFC 4648, excluding padding)
base64urlsafe = ALPHA / DIGIT / "-" / "_"

; The complete SAID primitive MUST conform to CESR code table [2], CESR spec Section 11.4.
; The following currently defined digest codes, for example, produce SAIDs of 44 or 88 characters total.
;
; 256-bit SAIDs: 44 characters total (1 char code + 43 Base64URLSafe)
; one-char-code = "E" / "F" / "G" / "H" / "I"
; said-256 = one-char-code 43base64urlsafe

; 512-bit SAIDs: 88 characters total (2 char code + 86 Base64URLSafe)
; two-char-code = "0D" / "0E" / "0F" / "0G"
; said-512 = two-char-code 86base64urlsafe
```

Examples:

  - `urn:said:E8wYuBjhslETYaLZcxMkWrhVbMcA8RS1pKYl7nJ77ntA` (44 characters, Blake3-256)
  - `urn:said:0FCNcm3MGi3efpdqsmmzGU2tnEPpAndgeCQErutCuu82VfaZqc1BbxL0a2-fOrGilCK2XuHcMqtILo2nc7M2mUuw` (88 characters, SHA3-512)

The first example is 44 characters long in text representation, where `E` indicates Blake3-256 digest and the remaining 43 characters encode 256 bit digest. The second example has a two character code `0F`, followed by 86 characters encoding 512 bit SHA3-512 digest. Additional digest functions are listed in CESR Spec code table, Section 11.4.2 [2].

Assignment: 

The SAID strings conforming to this scheme are self-assigned, based on the derivation of the SAID as per CESR Spec [1]. 

CESR (Composable Event Streaming Representation) is a dual text-binary encoding format providing lossless round-trip conversion between text (Base64URLSafe) and binary domains. CESR primitives are self-framing: each primitive includes a prepended type code identifying both the cryptographic algorithm and value length, enabling stream parsing without external delimiters. A Self-Addressing Identifier (SAID) is derived by: (1) designating a location within the data for the SAID, (2) inserting a placeholder of the appropriate length at that location, (3) computing a cryptographic digest over the entire byte sequence, and (4) replacing the placeholder with the CESR-encoded digest. The placeholder length equals the final SAID length: 33 bytes in the binary domain or 44 characters in the text domain for a 256-bit digest. Verification reverses this process. The CESR type code (e.g., E for Blake3-256) makes the digest algorithm self-describing, providing cryptographic agility.

The digital assets identified by an `urn:said` identifier must contain the SAID identifier in itself (i.e. self-referential). The SAID derivation procedure defined by CESR Spec [1] (Section 11.6) requires a consistent serialization scheme for the digital assets in order for correct representation and verification. In other words, a SAID identifies the serialized digital asset where it is also contained.

The serialization scheme used for SAID derivation must be known to verifiers. This is typically established by the application context or protocol in which the SAID appears. The serialization scheme information is not encoded in the SAID. Note that applications can choose their own serialization schemes, but for reproducibility and verification, the chosen scheme must preserve the size and order of data fields in the structure. For interoperability over a network, standardized serialization methods such as JSON, CBOR, MessagePack, and CESR can be used.

To illustrate, here are some examples of how the derivation works (from CESR [1], Section 11.6):

(1) CESR format example

Suppose the initial value of the fixed field serialization is the 76-character string as follows:

field_0_01234567field_1_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789field_2_98765432

where:
field0 is the 16-character string “field_0_01234567” field1 is the 44-character placeholder string “field_1_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789” field2 is the 16 character string “field_2_98765432”

The first step to generating the SAID for this serialization is to replace the placeholder contents of field1 with a dummy string of # characters of length 44. This produces a dummied 76-character string as follows:

field_0_01234567############################################field_2_98765432

Let's say we choose to use Blake3-256. The digest is then computed on the above string and encoded in CESR format. This is the SAID of the 76-character string as follows:

ENI2bDYghiu1KYYkFrPofH8tJ5tNiNt8WrTIc4s_5IIH

Replacing the 44 dummy characters with the SAID of the same length produces the final SAIDified string as follows:

field_0_01234567ENI2bDYghiu1KYYkFrPofH8tJ5tNiNt8WrTIc4s_5IIHfield_2_98765432

To verify the embedded SAID with respect to its encompassing serialization above, just reverse the generation steps. In other words, replace the SAID in the string with dummy characters of the same length, compute the Blake3 digest as SAID of this dummied version, and then compare the SAIDs.

The resulting URN:
`urn:said:ENI2bDYghiu1KYYkFrPofH8tJ5tNiNt8WrTIc4s_5IIH`

(2) JSON serialized data example

Suppose the initial value of Python dict data structure is as follows:
{
    "said": "",
    "first": "Sue",
    "last": "Smith",
    "role": "Founder"
}

If we choose the 44 CESR character Blake3-256 digest for SAID derivation and use JSON serialization, the first step of the derivation procedure is to insert the `#` character in place of the future SAID string:
{
    "said": "############################################",
    "first": "Sue",
    "last": "Smith",
    "role": "Founder"
}

For consistent JSON serialization, we remove all extra white space:
{"said":"############################################","first":"Sue","last":"Smith","role":"Founder"}

Apply Blake3-256 digest algorithm to this representation, we obtain the SAID (encoded in CESR) string (in text format):
EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ

Now, replace the `#` spaceholder with the SAID string, the data asset with the SAID becomes:
{"said":"EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ","first":"Sue","last":"Smith","role":"Founder"}

The URN for the above data representation is:
`urn:said:EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ`

Now, the Python data structure may be updated to:
{
    "said": "EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ",
    "first": "Sue",
    "last": "Smith",
    "role": "Founder"
}

The verification of SAID (therefore `urn:said`) reverses the generation process. Note that the data fields do not have to be text; they can be binary, but must be fixed in size / consistent in order for verification to work.

The resulting URN:
`urn:said:EJymtAC4piy_HkHWRs4JSRv0sb53MZJr8BQ4SMixXIVJ`

(3) JSON Schema $id example

Applying the same procedure as the above example, we produce this self-referential JSON Schema:

{
    "$id": "EGU_SHY-8ywNBJOqPKHr4sXV9tOtOwpYzYOM63_zUCDW",
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "full_name": {
            "type": "string"
        }
    }
}

The resulting URN:
`urn:said:EGU_SHY-8ywNBJOqPKHr4sXV9tOtOwpYzYOM63_zUCDW`

(4) Binary data example

Suppose a fixed-format binary record with the following layout:

Offset      Size        Field
0           2           Record type (big-endian)
2           33          SAID slot (256-bit, binary domain)
35          4           Payload

Step 1: Initial data with placeholder
The application defines a record with type 0x0001 and payload 0xDEADBEEF. Insert 33 placeholder bytes (0x23 = #) at the SAID slot:

Hex: 0001 23232323232323232323232323232323
          23232323232323232323232323232323
          23 DEADBEEF
Total: 39 bytes

Step 2: Compute digest
Apply Blake2b-256 over the 39-byte sequence, yielding the 32-byte digest:

116a3b1b50225060df5c2bf4154a2539b5ae9345ddc68f0c4fd59f5bd64757b2

Step 3: Encode as CESR
Text domain (44 characters):
FBFqOxtQIlBg31wr9BVKJTm1rpNF3caPDE_Vn1vWR1ey

Note that we choose Blake2b-256 in this example whose one character code is `F`.

Binary domain (33 bytes):
14116a3b1b50225060df5c2bf4154a2539b5ae9345ddc68f0c4fd59f5bd64757b2

Step 4: Replace placeholder with SAID

Final binary record (39 bytes):
Hex: 0001 14116a3b1b50225060df5c2bf4154a25
          39b5ae9345ddc68f0c4fd59f5bd64757
          b2 DEADBEEF
URN:
urn:said:FBFqOxtQIlBg31wr9BVKJTm1rpNF3caPDE_Vn1vWR1ey

Note that the `said` identifier is a Base64URLSafe character string for `urn:said` identifiers. The SAID contained in the binary data structure is in binary.

Security and Privacy: 

`urn:said` identifiers are designed to identify digital assets. Do not assume they are random or hard to guess. In fact, if the digital content itself is known they can be deterministically derived for a given digest algorithm. Such identifiers, therefore, should not be naively used for security capabilities (identifiers whose mere possesion grants privileged access).

The SAID must be encoded with one of the digest algorithms provided in the CESR code tables, as defined in Section 11.1 of CESR specification[2] (which may be viewed as the security considerations for SAID). This normative requirement is that cryptographic primitives that are entered in the table must maintain 128 bits of cryptographic strength. This strength protects against attempts to alter the binding between a `urn:said` identifier and its self-referenced content. Additional digest algorithms may be added to the code table in the future, e.g. for approved NIST post-quantum resistant cryptographic operations.

Adding `urn:said` identifier to the self-referenced digital asset does not change privacy considerations.

Interoperability: 

A SAID string MUST be CESR encoded which self-identifies the digest algorithm used to generate it. This greatly enhances interoperability and future adaptability. In addition, the use of CESR encoding allows lossless transformation between binary and text domains. This property is useful in digital assets which may be most optimally represented in binary or serialization schemes such as CBOR.

The serialization method used MUST be known out of band or by context by the verifiers.

Adopters MAY consider narrowing selections of digest functions to reduce complexity and improve interoperability with some cost in flexibility.

Resolution:

These URNs are non-resolvable and serve as globally unique identifiers. In future, however, we may extend this scheme with optional information for easier resolution.

Documentation: 

- [1] CESR: omposable Event Streaming Representation, https://trustoverip.github.io/kswg-cesr-specification
- [2] CESR Code Table: Composable Event Streaming Representation (CESR) Genus AAA, the latest code table (the current version at the time of this application: CAA, i.e. 2.0), https://trustoverip.github.io/kswg-cesr-specification/#keriacdc-protocol-genus-version-table
- [3] RFC 4648: The Base16, Base32, and Base64 Data Encodings, https://datatracker.ietf.org/doc/html/rfc4648

Additional Information:  NONE

Revision Information:  N/A