Skip to content

Add IntegrityUtils#2463

Draft
rreminy wants to merge 1 commit into
goatcorp:masterfrom
rreminy:integrity-utils
Draft

Add IntegrityUtils#2463
rreminy wants to merge 1 commit into
goatcorp:masterfrom
rreminy:integrity-utils

Conversation

@rreminy

@rreminy rreminy commented Nov 17, 2025

Copy link
Copy Markdown
Contributor

As discussed starting from here: https://discord.com/channels/581875019861328007/929533532185956352/1439479968118603786

IntegrityUtils provide a method to compute the HMACSHA256 of a directory recursively with a specified key. All directories and files are sorted before being read for hashing to provide a consistent order.

The following are hashed:

  • The entire directory structure recursively
    • Only their paths of each directory is included in the hash.
  • All files recursively
    • Their path, size and content are included in the hash.

All paths are normalized to use / for cross-platform compatibility. Are paths will be relative to the starting directory.

This utility method is intended to be called from IDalamudPlugin.CheckOwnIntegrity(K) mentioned here: https://discord.com/channels/581875019861328007/929533532185956352/1439489383290896465

@rreminy rreminy requested a review from a team as a code owner November 17, 2025 06:11
@KazWolfe

KazWolfe commented Nov 17, 2025

Copy link
Copy Markdown
Member

A note:

Hashing directory paths, file names, sizes, etc. seems completely excessive to me. It'd be just as effective to concat all files into a single bytestream and not have to deal with any sort of data structure complexity. I think sorting is reasonable, but file names/sizes won't make any sort of difference for integrity verification even in the best case (a new file, removed file, or appended/trimmed file all change the hash input). If we are to implement this, we should really keep it simple.


And a thought:

Ideally, though, we'd be generating hashlists and attestations for plugins anyways and including them in release zips. This can be chained into integrity verification as well, including attestation metadata as part of a larger AttestationResult.

In such a chained attestation, Dalamud will still validate that the .hashes file is correct and HMAC can be performed against that file. If an adversary were to tamper with a binary and not update the .hashes.txt file, Dalamud would report a failed attestation (returning nothing). If the adversary did update the .hashes.txt file, the HMAC-SHA of that file would still be unexpected to the checker.

The only real difference I can see is this approach would only require an attacker ship a single (untainted) record of original hashes alongside their tampered plugin, rather than a copy of all binaries. In either case, though, they'd have to modify plugin code to patch out the Dalamud check in favor of their own design. I'm uncertain if this would be acceptable though - the ultimate security level would remain basically the same in terms of difficulty to patch out.

@rreminy

rreminy commented Nov 17, 2025

Copy link
Copy Markdown
Contributor Author

I made this on the understanding of the conversation we had, however I do like the idea of having a hashes file containing the hash of every file. I'll work on an initial implementation to hash every file separately and see how it goes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants