This article was co-authored with generative AI. Facts have been checked against public documentation where feasible, but errors may remain. Please verify primary sources before relying on this for important decisions.
"What is the difference between a UUID and a SHA-256 digest?" and "can they make anything uniquely identifiable?" are both questions that become vague when answered in the abstract. This piece works through them using the PREMIS (Preservation Metadata: Implementation Strategies) Data Dictionary alongside the files that systems implementing it actually write out. Looking at where a working standard places each of the two makes the division of labour clearer than comparing them in isolation.
The primary sources referenced here are:
- PREMIS Data Dictionary for Preservation Metadata, version 3.0 (June 2015 – Revised November 2015, PREMIS Editorial Committee)
- Archivematica 1.18 documentation and the
artefactual/archivematicasource code (qa/1.xbranch) - E-ARK (European Archival Records and Knowledge Preservation) CITS (Content Information Type Specification) Preservation Metadata v1.0.0 (2021-08-31, DILCIS Board (Digital Information LifeCycle Interoperability Standards Board))
- Library of Congress controlled vocabularies (
id.loc.gov)
The two questions sit in separate fields of PREMIS
Two pieces of background first.
One is that PREMIS models an Object at four levels: Intellectual Entity (the resource as a single conceptual thing), Representation (the set of files making up that resource — an original set and a preservation set are different representations), File, and Bitstream (a portion within a file). The levels get more concrete going down.
The other is the layout of the Data Dictionary. It is a table in which each semantic unit (a unit of meaning, appearing as an element in XML) carries a fixed set of fields: Definition, Rationale, Obligation, Repeatability, Applicability, Data constraint, Usage notes, and so on. When this article says "the obligation is Mandatory", it refers to the value of one of those fields.
With that in place: the PREMIS Object entity provides a separate field for identifiers and for checksums. This is not two ways of writing the same thing — they answer different questions.
Section 1.1 objectIdentifier of the Data Dictionary is defined as follows.
A designation used to identify the Object uniquely within the preservation repository system in which it is stored.
Its obligation is Mandatory, it is Repeatable, and it applies at all four levels. The reason it repeats is stated in the Usage notes: so that both repository-assigned and externally-assigned identifiers can be recorded.
Section 1.5.2 fixity is defined this way.
Information used to verify whether an object has been altered in an undocumented or unauthorized way.
Here the obligation is Optional, and applicability is limited to File and Bitstream. For Intellectual Entity and Representation it is explicitly marked "Not applicable". If fixity is present, however, the messageDigestAlgorithm and messageDigest inside it are Mandatory. This follows a general rule stated in the Data Dictionary's conventions: a mandatory unit inside an optional container is required if and only if the container exists. What is optional is whether to record a checksum at all; once you do, the contents have to be complete.
The Usage notes also explain why it does not apply at the representation level. If a representation consists of a single file, or if all its files are combined into one (for example, zipped), it looks as though a fixity check could be performed on the representation. In practice the check is being performed on a file that happens to coincide with a representation.
The same passage adds a note on terminology.
(Note that the terms "message digest" and "checksum" are commonly used interchangeably. However, the term "checksum" is more correctly used for the product of a cyclical redundancy check (CRC), whereas the term "message digest" refers to the result of a cryptographic hash function, which is what is referred to here.)
This is the background to the semantic unit being named messageDigest rather than "checksum".
Reading the METS that Archivematica writes
Definitions alone make the division hard to see, so consider what an implementation actually produces. Archivematica is an open-source digital preservation system that writes AIP (Archival Information Package) metadata as PREMIS embedded in METS (Metadata Encoding & Transmission Standard). METS has sections such as dmdSec for descriptive metadata and techMD for technical metadata, and PREMIS Objects go there.
The examples below all come from the Archivematica 1.18 documentation, excerpted with namespace declarations and empty elements removed. First, the dmdSec at the intellectual entity level.
<premis:object xsi:type="premis:intellectualEntity" version="3.0">
<premis:objectIdentifier>
<premis:objectIdentifierType>UUID</premis:objectIdentifierType>
<premis:objectIdentifierValue>6a82ffa2-91e2-48e1-b0d0-55b0de21568e</premis:objectIdentifierValue>
</premis:objectIdentifier>
<premis:objectIdentifier>
<premis:objectIdentifierType>ULID</premis:objectIdentifierType>
<premis:objectIdentifierValue>01D9T8MJM9NEQ390H239VT50CQ</premis:objectIdentifierValue>
</premis:objectIdentifier>
<premis:objectIdentifier>
<premis:objectIdentifierType>EXID</premis:objectIdentifierType>
<premis:objectIdentifierValue>https://example.com/AIP/id/1348554167</premis:objectIdentifierValue>
</premis:objectIdentifier>
<premis:originalName>demo-1-6a82ffa2-91e2-48e1-b0d0-55b0de21568e</premis:originalName>
</premis:object>
Three identifiers sit on a single intellectual entity. The UUID and the ULID (Universally Unique Lexicographically Sortable Identifier, which sorts in creation-time order) are both assigned by the repository, while EXID holds the external identifier. Beyond the "internal and external" pairing the Usage notes describe, this adds a second internal scheme. There is no fixity here, exactly as the specification requires for intellectual entities.
Next, the techMD at file level.
<premis:object xsi:type="premis:file" version="3.0">
<premis:objectIdentifier>
<premis:objectIdentifierType>UUID</premis:objectIdentifierType>
<premis:objectIdentifierValue>d8717b3a-d12c-408a-9c37-732425331f44</premis:objectIdentifierValue>
</premis:objectIdentifier>
<premis:objectCharacteristics>
<premis:compositionLevel>0</premis:compositionLevel>
<premis:fixity>
<premis:messageDigestAlgorithm>sha256</premis:messageDigestAlgorithm>
<premis:messageDigest>1cad1038c85dde1d018116c15fd32d2dac34d645b548611eb042f37169fcdee0</premis:messageDigest>
</premis:fixity>
<premis:size>47941948</premis:size>
<premis:format>
<premis:formatDesignation>
<premis:formatName>Tagged Image File Format</premis:formatName>
</premis:formatDesignation>
</premis:format>
</premis:objectCharacteristics>
<premis:originalName>%SIPDirectory%objects/View_from_lookout_over_Queenstown_towards_the_Remarkables_in_spring-d8717b3a-d12c-408a-9c37-732425331f44.tif</premis:originalName>
</premis:object>
This is where a UUID and a SHA-256 digest first appear inside the same Object. The UUID says which file this is; the SHA-256 digest exists so that the content can later be verified as unchanged. The UUID is also embedded in originalName, so the identifier travels with the filename as well.
Note that this object is not the file as received but the normalized preservation copy. Later in the same document this file names another object as its source (see below), and the entry under fileSec with USE="original" is a JPEG carrying a different UUID. The UUID appended to the filename is also how normalized files are named.
The Archivematica documentation states that the checksum algorithm can be chosen from MD5, SHA-1, SHA-256 and SHA-512.
You can select which checksum algorithm Archivematica will use during the Assign UUIDs and checksums microservice in Transfer. Choose between MD5, SHA-1, SHA-256 and SHA-512.
The documentation does not appear to state the default, but the source code defines it (src/archivematica/MCPClient/settings/common.py):
DEFAULT_CHECKSUM_ALGORITHM = "sha256"
A fixity check is recorded as an Event, not on the Object
Another design point worth noting is where the fact of having run a check is written. The Data Dictionary's Usage notes say:
The act of performing a fixity check and the date it occurred would be recorded as an Event. The result of the check would be recorded as the eventOutcome. Therefore, only the messageDigestAlgorithm and messageDigest need to be recorded as objectCharacteristics for future comparison.
So the Object carries only the value used for comparison, while when the comparison ran and how it came out accumulates on the Event side. The fixity check Event in the Archivematica documentation illustrates this.
<premis:event version="3.0">
<premis:eventIdentifier>
<premis:eventIdentifierType>UUID</premis:eventIdentifierType>
<premis:eventIdentifierValue>8c6714b3-ab18-44e2-8507-80691ad1dafa</premis:eventIdentifierValue>
</premis:eventIdentifier>
<premis:eventType>fixity check</premis:eventType>
<premis:eventDateTime>2019-11-14T11:00:50.632264+00:00</premis:eventDateTime>
<premis:eventDetailInformation>
<premis:eventDetail>program="sha512sum -c --strict .../metadata/checksum.sha512"; version="sha512sum (GNU coreutils) 8.28"</premis:eventDetail>
</premis:eventDetailInformation>
<premis:eventOutcomeInformation>
<premis:eventOutcome>pass</premis:eventOutcome>
</premis:eventOutcomeInformation>
</premis:event>
The Event identifier is a UUID as well. The eventType value fixity check comes from a Library of Congress controlled vocabulary, which also registers message digest calculation (computing the digest itself) as a separate term. As far as I could check, that eventType vocabulary holds 50 terms.
What is interesting here is that the file-level fixity uses sha256 while this Event runs sha512sum. The referenced metadata/checksum.sha512 is a checksum file supplied by the depositor as part of the transfer. The Archivematica documentation describes verifying externally created MD5, SHA1, SHA256 and SHA512 checksums during the Verify transfer checksums microservice, and the docstring of the source (clientScripts/verify_checksum.py) describes verifying "checksums provided to the system as part of a transfer, e.g. checksum.md5 in the transfer metadata folder". The difference between the two is therefore not the granularity of verification but the provenance of the digest — who calculated it. The Data Dictionary's special topic also mentions using more than one algorithm:
In fact, it is common to create and test two or more message digests using different algorithms to be certain that an object is fixed.
This corresponds to fixity being Repeatable.
Normalization changes the hash; the identifier is what connects them
Digital preservation often involves normalization — converting a received file into a format better suited to long-term preservation. Because the byte stream changes, the message digest necessarily becomes a different value.
The file-level example above continues with a relationship.
<premis:relationship>
<premis:relationshipType>derivation</premis:relationshipType>
<premis:relationshipSubType>has source</premis:relationshipSubType>
<premis:relatedObjectIdentifier>
<premis:relatedObjectIdentifierType>UUID</premis:relatedObjectIdentifierType>
<premis:relatedObjectIdentifierValue>d0c46bbb-63b1-4530-ad1f-f65d9a32e434</premis:relatedObjectIdentifierValue>
</premis:relatedObjectIdentifier>
<premis:relatedEventIdentifier>
<premis:relatedEventIdentifierType>UUID</premis:relatedEventIdentifierType>
<premis:relatedEventIdentifierValue>d7746761-d98c-4a78-80e0-2e91e4c187d4</premis:relatedEventIdentifierValue>
</premis:relatedEventIdentifier>
</premis:relationship>
The file created by normalization (d8717b3a…) names the original file (d0c46bbb…) as its source. What links the two is the identifier in relatedObjectIdentifier, not a hash. The relatedEventIdentifier additionally points at the Event (the conversion) that produced the derivative.
This is the concrete form of the point that a hash alone cannot carry identity. A hash mismatch says only that the byte streams differ. What allows you to say "this is the same resource in another form" is a separately recorded relationship naming the counterpart by identifier. Conversely, a hash match says only that the byte streams are the same (barring the deliberate collisions discussed below). If the same PDF is accepted into two different collections, the two Objects will carry the same digest but separate identifiers. In the extreme case, any two empty files always produce the same digest under the same algorithm.
The E-ARK specification has the same structure
To check that this is not specific to Archivematica, consider the European E-ARK specifications. The DILCIS Board's CITS Preservation Metadata v1.0.0 defines how PREMIS is used within E-ARK packages.
For identifiers, it states that where an identifier of type local is used its value should be unique within the PREMIS document and the repository (PREMIS-ID-LOCAL), and that other types may be added by repeating the objectIdentifier element (PREMIS-ID-OTHER). The three examples it gives are:
<objectIdentifier>
<objectIdentifierType>local</objectIdentifierType>
<objectIdentifierValue>fileId001</objectIdentifierValue>
</objectIdentifier>
<objectIdentifier>
<objectIdentifierType>UUID</objectIdentifierType>
<objectIdentifierValue>5707ecac-6713-41b5-826a-3388e21c4c2f</objectIdentifierValue>
</objectIdentifier>
<objectIdentifier>
<objectIdentifierType>filepath</objectIdentifierType>
<objectIdentifierValue>metadata/file.xml</objectIdentifierValue>
</objectIdentifier>
For checksums, SHA-256 is the recommendation.
PREMIS-CHECKSUMS: Checksums SHOULD be provided as a descendant of the "objectCharacteristics" element information in the form of the recommended SHA-256 hashsum, a fixed size 256-bit value.
Its example puts /usr/bin/sha256sum in messageDigestOriginator, showing the practice of recording which agent computed the first digest. The Rationale for that semantic unit is that verifying a digest calculated by the depositor confirms the file as received matches the file as sent, and that where no digest is supplied the repository must calculate the initial value — so knowing which agent produced it is useful. The Archivematica Event seen earlier, verifying a depositor's checksums, is exactly the situation this Rationale anticipates.
Archivematica's implementation and the CITS specification were produced separately, yet they share both the use of multiple identifiers and the use of SHA-256 for fixity.
Putting numbers on "can this identify anything uniquely?"
With the division of labour established, back to the other question. UUIDs and digests are both finite bit strings, so duplicate values become unavoidable as counts grow — but the reasoning differs between them. A hash function maps a larger input space onto a smaller output space, so by the pigeonhole principle (put n+1 items into n containers and some container must hold two) collisions must exist. A UUID is not derived from an input but issued from randomness, so collisions remain a matter of probability rather than necessity.
To see how far away that is in practice, here is the birthday bound (the count at which collision probability reaches 50%, roughly 1.1774 × √(2^bits)).
| Subject | Bits | Count at 50% collision probability |
|---|---|---|
| UUIDv4 | 122 (random portion) | approx. 2.7 × 1018 |
| MD5 | 128 | approx. 2.2 × 1019 |
| SHA-1 | 160 | approx. 1.4 × 1024 |
| SHA-256 | 256 | approx. 4.0 × 1038 |
The birthday bound measures whether a set contains a duplicate, so it maps directly onto identifier uniqueness. Fixity is concerned instead with a single comparison — whether one corrupted file yields the same digest as before. The figures are lined up here as a common yardstick for orders of magnitude.
That UUIDv4 has 122 random bits is specified in RFC 9562 (May 2024, obsoleting RFC 4122). Generating a trillion (1012) UUIDv4 values gives roughly a 9.4 × 10-14 chance of at least one collision — not a level that matters at repository scale. RFC 9562 itself does not claim absolute uniqueness; it says implementations should weigh the consequences of collisions within their own application.
Separately from accidental collisions, there is the question of whether collisions can be produced deliberately. For SHA-1, an actual collision was published on 23 February 2017 by researchers at CWI Amsterdam and Google (SHAttered): two PDFs with different content sharing the SHA-1 value 38762cf7f55934b34d179ae6a4c80cadccbb7f0a. The count at which an accidental collision is expected is on the order of 1024, but producing one deliberately takes far less computation. The earlier statement that "a hash match means the same bytes" does not hold for an algorithm where collisions can be constructed. No comparable attack on SHA-256 appears to be known at present.
For preservation, the point is that fixity aims at detecting unintended alteration, and resistance to malicious tampering is a separate requirement. Catching bit rot (bits degrading on storage media over time) or copy corruption works well enough in practice even with MD5, but where tamper detection is included, SHA-256 or stronger seems to be the more common choice. RFC 8493 (October 2018) for BagIt (a packaging format that bundles files with a manifest) likewise states that tools must support SHA-256 and SHA-512 and should enable SHA-512 by default for new bags, while MD5 and SHA-1 should be supported for backwards compatibility.
Implementations write the values differently
Placing implementations side by side reveals that the values are not written consistently.
For messageDigestAlgorithm, the Data Dictionary asks that values be taken from a Library of Congress controlled vocabulary (the Data constraint says "should"). Retrieving that cryptographicHashFunctions vocabulary gives 13 terms at the time of writing, with these authoritative labels and codes.
| code | label |
|---|---|
adler | Adler-32 |
crc32 | CRC32 |
haval | HAVAL |
md2 | MD2 |
md5 | MD5 |
mnp | MNP |
sha1 | SHA-1 |
sha256 | SHA-256 |
sha384 | SHA-384 |
sha512 | SHA-512 |
tiger | TIGER |
unk | unknown |
whirl | Whirlpool |
The vocabulary is named cryptographicHashFunctions, yet it includes non-cryptographic entries such as CRC32 and Adler-32; the terminology note quoted earlier and the contents of this vocabulary do not map onto each other exactly. From the changesets in the retrieved data, it appears to have been created in 2010 and updated in 2012 and September 2018. Using SHA-3 or BLAKE2 / BLAKE3 as a value would fall outside the vocabulary.
Looking at implementations against that: Archivematica writes sha256 (the code form), the CITS example writes SHA-256 (the label form), and the Data Dictionary's own examples use SHA-256. Both forms are within the vocabulary, yet they do not match as strings. Aggregating PREMIS from multiple repositories means normalizing this kind of variation before comparing.
The same applies to identifier types. The Data constraint for objectIdentifierType points to http://id.loc.gov/vocabulary/identifiers.html, but retrieving that vocabulary gives 232 terms, and uuid was not among them (local, "Locally defined identifier", along with doi, hdl, ark and urn, are included). Archivematica and CITS both use UUID as the value directly, which puts it outside the vocabulary.
That said, the Data Dictionary allows the identifier type to be implicit within the repository as long as it can be made explicit on dissemination.
The type of the identifier may be implicit within the repository as long it is can be explicitly communicated when the digital object is disseminated outside of it.
CITS likewise states that identifier types are an implementation-specific matter and that it neither recommends nor requires vocabularies for them. Since strict control is not being demanded, implementations using their own type names is within expectations. It is still something to check in advance if you intend to match values mechanically.
Incidentally, the word "UUID" appears only once in the body of PREMIS 3.0 as far as I could check: in the Examples for eventIdentifierType, alongside FDA, Stanford Repository Event ID and local. Using UUIDs is not a PREMIS requirement but an implementation choice.
What fixity does not guarantee
Finally, the distinction drawn in the PREMIS special topic "Fixity, integrity, authenticity" is worth quoting. Three concepts are separated there.
While this procedure can indicate with some confidence that an object has not changed over time, it does not address the object's integrity or authenticity.
A fixity check can only say that something has not changed since a given point. For integrity, format identification and validation are described as key, with tools such as JHOVE (JSTOR/Harvard Object Validation Environment, a format validation tool) cited — and these too are recorded as Events. Authenticity is described as ultimately a matter of human judgment, supported by evidence such as documentation of digital provenance, preservation of a bit-wise identical copy of the content as submitted, retention of significant properties, and digital signatures.
Storing a digest covers only part of that body of evidence. "It is authentic because we recorded a SHA-256 digest" does not follow; the digest acquires meaning only in combination with a record of who computed it, when, and which Events the object has passed through since.
Summary
| UUID (objectIdentifier) | SHA-256 (fixity / messageDigest) | |
|---|---|---|
| Question answered | Which thing is this? | Has this content changed? |
| How the value arises | Issued (UUIDv4 from randomness) | Derived from content (deterministic) |
| Relation to content | None; unchanged when content changes | A different value if one byte changes |
| Obligation in PREMIS | Mandatory | Optional (contents mandatory if present) |
| Applicability in PREMIS | Intellectual Entity, Representation, File, Bitstream | File and Bitstream only |
| Repeatable | Yes (multiple identifier schemes) | Yes (multiple algorithms) |
| Values seen in implementations | UUID / ULID / EXID / local / filepath | sha256 / SHA-256 |
On the opening question of whether anything can be uniquely identified, a three-layer view seems the practical one: mathematically collisions are unavoidable because the space is finite; practically the orders of magnitude are far enough apart not to matter; operationally things break for entirely different reasons. The third layer is the awkward one. Digests changing with every normalization, algorithm names not matching as strings across implementations, and identifier type names falling outside the referenced vocabulary are none of them probabilistic problems. One way to read PREMIS making identifiers repeatable and providing relationship and Event as separate constructs is that it happens to help with this layer.
Sources
- PREMIS Data Dictionary for Preservation Metadata, Version 3.0 (PDF)
- METS in Archivematica | Documentation (Archivematica 1.18.0)
- Transfer | Documentation (Archivematica 1.18.0)
- Dashboard Administration tab | Documentation (Archivematica 1.18)
- artefactual/archivematica
src/archivematica/MCPClient/settings/common.py - artefactual/archivematica
clientScripts/verify_checksum.py - CITS Preservation Metadata v1.0.0 (DILCIS Board)
- PREMIS Cryptographic Hash Functions vocabulary (id.loc.gov)
- PREMIS Event Type vocabulary (id.loc.gov)
- Standard Identifiers vocabulary (id.loc.gov)
- RFC 9562: Universally Unique IDentifiers (UUIDs)
- RFC 8493: The BagIt File Packaging Format (V1.0)
- SHAttered (announcement of the SHA-1 collision)


Comments
…