{"id":16340756,"url":"https://github.com/casey/filepack","last_synced_at":"2026-01-18T10:11:21.846Z","repository":{"id":255437800,"uuid":"850495932","full_name":"casey/filepack","owner":"casey","description":"#⃣ file verification utility","archived":false,"fork":false,"pushed_at":"2025-07-30T23:35:38.000Z","size":386,"stargazers_count":44,"open_issues_count":6,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-19T09:27:19.441Z","etag":null,"topics":["checksum","command-line-tool"],"latest_commit_sha":null,"homepage":"https://filepack.com/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/casey.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-31T23:58:26.000Z","updated_at":"2025-07-26T15:22:44.000Z","dependencies_parsed_at":"2024-09-14T20:33:50.058Z","dependency_job_id":"6f7ca3fc-5f08-46b3-bc91-bacbe368d857","html_url":"https://github.com/casey/filepack","commit_stats":{"total_commits":73,"total_committers":1,"mean_commits":73.0,"dds":0.0,"last_synced_commit":"364ea2c944234f3a3f59a1527888d22e5052c2f8"},"previous_names":["casey/filepack"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/casey/filepack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/casey%2Ffilepack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/casey%2Ffilepack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/casey%2Ffilepack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/casey%2Ffilepack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/casey","download_url":"https://codeload.github.com/casey/filepack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/casey%2Ffilepack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271895211,"owners_count":24840091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["checksum","command-line-tool"],"created_at":"2024-10-10T23:57:44.665Z","updated_at":"2026-01-18T10:11:21.835Z","avatar_url":"https://github.com/casey.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=right\u003eTable of Contents↗️\u003c/div\u003e\n\n\u003ch1 align=center\u003e\u003ccode\u003efilepack\u003c/code\u003e\u003c/h1\u003e\n\n\u003cdiv align=center\u003e\n  \u003ca href=https://crates.io/crates/filepack\u003e\n    \u003cimg src=https://img.shields.io/crates/v/filepack.svg alt=\"crates.io version\"\u003e\n  \u003c/a\u003e\n  \u003ca href=https://github.com/casey/filepack/actions\u003e\n    \u003cimg src=https://github.com/casey/filepack/actions/workflows/ci.yaml/badge.svg alt=\"build status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=https://github.com/casey/filepack/releases\u003e\n    \u003cimg src=https://img.shields.io/github/downloads/casey/filepack/total.svg alt=downloads\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n`filepack` is a command-line file hashing and verification utility written in\nRust.\n\nIt is an alternative to `.sfv` files and tools like `shasum`. Files are hashed\nusing [BLAKE3](https://github.com/BLAKE3-team/BLAKE3/), a fast, cryptographic\nhash function.\n\nA manifest named `filepack.json` containing the hashes of files in a directory\ncan be created with:\n\n```shell\nfilepack create path/to/directory\n```\n\nWhich will write the manifest to `path/to/directory/filepack.json`.\n\nFiles can later be verified with:\n\n```shell\nfilepack verify path/to/directory\n```\n\nTo protect against accidental or malicious corruption, as long as the manifest\nhas not been tampered with.\n\nIf you run `filepack` a lot, you might want to `alias fp=filepack`.\n\n`filepack` is currently unstable: the interface and file format may change at\nany time. Additionally, the code has not been extensively reviewed and should\nbe considered experimental.\n\nInstallation\n------------\n\n`filepack` is written in [Rust](https://www.rust-lang.org/) and can be built\nfrom source and installed from a checked-out copy of this repo with:\n\n```sh\ncargo install --path .\n```\n\nOr from [crates.io](https://crates.io/crates/filepack) with:\n\n```sh\ncargo install filepack\n```\n\nSee [rustup.rs](https://rustup.rs/) for installation instructions for Rust.\n\n### Pre-Built Binaries\n\nPre-built binaries for Linux, MacOS, and Windows can be found on\n[the releases page](https://github.com/casey/filepack/releases).\n\nYou can use the following command on Linux, MacOS, or Windows to download the\nlatest release, just replace `DEST` with the directory where you'd like to put\n`filepack`:\n\n```sh\ncurl --proto '=https' --tlsv1.2 -sSf https://filepack.com/install.sh | bash -s -- --to DEST\n```\n\nFor example, to install `filepack` to `~/bin`:\n\n```sh\n# create ~/bin\nmkdir -p ~/bin\n\n# download and extract filepack to ~/bin/filepack\ncurl --proto '=https' --tlsv1.2 -sSf https://filepack.com/install.sh | bash -s -- --to ~/bin\n\n# add `~/bin` to the paths that your shell searches for executables\n# this line should be added to your shell's initialization file,\n# e.g. `~/.bashrc` or `~/.zshrc`\nexport PATH=\"$PATH:$HOME/bin\"\n\n# filepack should now be executable\nfilepack --help\n```\n\nNote that `install.sh` may fail on GitHub Actions or in other environments\nwhere many machines share IP addresses. `install.sh` calls GitHub APIs in order\nto determine the latest version of `filepack` to install, and those API calls\nare rate-limited on a per-IP basis. To make `install.sh` more reliable in such\ncircumstances, pass a specific tag to install with `--tag`.\n\nUsage\n-----\n\nFilepack supports a number of subcommands, including `filepack create` to\ncreate a manifest, and `filepack verify` to verify a manifest.\n\nSee `filepack help` for supported subcommands and `filepack help SUBCOMMAND`\nfor information about a particular subcommand.\n\n### `filepack create`\n\nCreate a manifest.\n\nRecommended lints can be enabled with:\n\n```shell\nfilepack create --deny distribution\n```\n\n### `filepack verify`\n\nVerify the contents of a directory against a manifest.\n\nTo verify the contents of `DIR` against `DIR/filepack.json`:\n\n```shell\nfilepack verify DIR\n```\n\nIf the current directory contains `filepack.json`, `DIR` can be omitted:\n\n```shell\nfilepack verify\n```\n\n`filepack verify` takes an optional `--print` flag, which prints the manifest\nto standard output if verification succeeds. This can be used in a pipeline to\nensure that you the manifest has been verified before proceeding:\n\n```shell\nfilepack verify --print | jq\n```\n\nManifest\n--------\n\n`filepack` manifests are conventionally named `filepack.json` and are placed\nalongside the files they reference.\n\nManifests are [UTF-8](https://en.wikipedia.org/wiki/UTF-8)-encoded\n[JSON](https://www.json.org/json-en.html).\n\nManifests contain an object with two mandatory keys, `files` and `notes`.\n\n### `files`\n\nThe value of the mandatory `files` key is an object mapping path components to\ndirectory entries. Directory entries may be subdirectories or files. Files are\nobjects with keys `hash`, the hex-encoded BLAKE3 hash of the file, and `size`,\nthe length of the file in bytes.\n\nAs a consequence of the manifest being UTF-8, all path components must be\nvalid Unicode.\n\nPath components may not be `.` or `..`, contain the path separators `/` or `\\`,\ncontain NUL, be longer than 255 bytes, or begin with a Windows drive prefix,\nsuch as `C:`.\n\n### `notes`\n\nThe value of the mandatory `notes` key is an array of signed notes. Notes are\nobjects containing a single mandatory key `signatures`, an object mapping\npublic keys to signatures. Public keys and signatures are both lowercase\nhexadecimal strings.\n\nNotes may optionally contain a `time` field whose value is a timestamp given as\nthe number of nanoseconds after the UNIX epoch.\n\nPublic keys are Curve25519 points and signatures are Ed25519 signatures made\nover the root of a Merkle tree which commits to the content of `files`, as well\nas the value of the `time` field, if present.\n\n### example\n\nAn manifest over a directory containing the files `README.md` and `src/main.c`,\nsigned by the public key\n`3c977ea3a31cd37f0b540f02f33eab158f2ed7449f42b05613c921181aa95b79`:\n\n```json\n{\n  \"files\": {\n    \"README.md\": {\n      \"hash\": \"fc253b84551ce6b00e820a826ac18054dc7f63a318ce62f3175315f5c467a62a\",\n      \"size\": 11883\n    },\n    \"src\": {\n      \"main.rs\": {\n        \"hash\": \"1fa48b95ed335369d45b91af8138bdccd1413364bcdbfa6e9034e8a2cfd6e17f\",\n        \"size\": 33\n      }\n    }\n  },\n  \"notes\": [\n    {\n      \"signatures\": {\n        \"3c977ea3a31cd37f0b540f02f33eab158f2ed7449f42b05613c921181aa95b79\": \"…\"\n      },\n      \"time\": 1768531681809767000\n    }\n  ]\n}\n```\n\nThe signature is a 128 character hexidecimal string and is elided for brevity.\n\nMetadata\n--------\n\nFilepack packages may contain a file named `metadata.yaml` describing the\npackage and its content.\n\n`filepack create` loads `metadata.yaml` if present and checks for validity and\nunknown fields.\n\n`filepack verify` also loads `metadata.yaml` if present and checks for\nvalidity. Unknown fields, however, are not an error, so that future versions of\n`filepack` may define new metadata fields in a backwards-compatible fashion.\n\nFilepack metadata is intended to a broadly useful machine and human readable\ndescription of the contents of a package, covering personal, distribution, and\narchival use-cases.\n\nMetadata follows a fixed schema and is not user-extensible. Future versions of\n`filepack` may define new metadata fields, causing verification errors if those\nfields are present and invalid according to the new schema.\n\nPlease feel free to open an issue with ideas for new metadata fields.\n\n### Schema\n\nFields are given as `NAME: TYPE`.\n\nMandatory fields:\n\n- `title: component`: The content's human-readable title.\n\nOptional fields:\n\n- `artwork: component.png`: The filename of an PNG file containing artwork for\n  the content, for example, cover art for an album or key art for a movie.\n\n- `creator: component`: The person or group who created the content.\n\n- `date: date`: The date the content was created or released.\n\n- `description: markdown`: A description of the content.\n\n- `homepage: url`: Primary URL for the content. Should be the official homepage\n  of the content, if any, and not, for example, a Wikipedia or media database\n  link.\n\n- `language: language`: The primary language of the content.\n\n- `package: object`: The package metadata.\n\n- `readme: component.md`: The filename of the content readme.\n\nOptional `package` field describing the package itself, as opposed its content:\n\n- `creator: component`: The person or group who created the package.\n\n- `creator-tag: tag`: The tag of the person or group who created the\n  package.\n\n- `date: date`: The date the package was created.\n\n- `description: markdown`: A description of the package.\n\n- `homepage: url`: Primary URL for the package.\n\n- `nfo: component.nfo`: The filename of the package nfo file.\n\nTypes:\n\n- `component`: A string with the same restrictions as path components in the\n  manifest `files` object, allowing them to be used as unix filesystem paths.\n  Note that Windows imposes additional restrictions which are not enforced, so\n  components may not be valid paths on Windows.\n\n- `component.EXTENSION`: A component that must end with `.EXTENSION`.\n\n- `date`: A string containing a date in one of several formats: as a year only,\n  when the date and time is unknown, a date only, when the time is unknown, or\n  a date and time with a mandatory time zone.\n\n- `language`: A string containing an ISO 639-1 two-character language code. See\n  `filepack languages` for valid language codes.\n\n- `markdown`: A string containing CommonMark markdown.\n\n- `tag`: A string containing a tag, commonly an abbreviation of a release group\n  name. Must match the regular expression `[0-9A-Z]+(\\.[0-9A-Z]+)*`.\n\n- `url`: A string containing a URL.\n\nExample dates:\n\n```tsv\n1970\n1970-01-01\n1970-01-01T00:00:00Z\n1970-01-01 00:00:00Z\n1970-01-01T00:00:00+00:00\n1970-01-01 00:00:00 +00:00\n```\n\n### Example\n\n```yaml\ntitle: Tobin's Spirit Guide\ncreator: John Horace Tobin\nartwork: cover.png\ndate: 1929\ndescription: A compilation of supernatural occurrences, entities, and facts.\nhomepage: https://tobin-society.org/spirit-guide\nlanguage: en\nreadme: README.md\npackage:\n  creator: Egon Spengler\n  creator-tag: ES\n  date: 1984-07-08 19:32:00 -04:00\n  description: \u003e\n    First edition on loan from NYPL Main Branch research stacks. Captured via\n    Microtek MS-300A flatbed scanner.\n  homepage: https://ghost-busters.net/~egon\n  nfo: tobins.nfo\n```\n\nThe `homepage` URLs are of course anachronistic, as the World Wide Web was\ncreated in 1989, some years after Egon first packaged Tobin's Spirit Guide.\n\nLints\n-----\n\n`filepack create` supports optional lints that can be enabled by group:\n\n```shell\nfilepack create --deny distribution\n```\n\nThe `distribution` lint group checks for issues which can cause problems if the\npackage is intended for distribution, such as non-portable paths that are\nillegal on Windows, paths which would conflict on case-insensitive file\nsystems, and inclusion of junk files such as `.DS_Store`.\n\nLint group names and the lints they cover can be printed with:\n\n```shell\nfilepack lints\n```\n\nKeys and Signatures\n-------------------\n\n`filepack` supports the generation of\n[Curve25519](https://en.wikipedia.org/wiki/Curve25519) public/private keypairs,\nand the creation and verification of\n[EdDSA](https://en.wikipedia.org/wiki/EdDSA) signatures over manifests.\n\n### Keypair Generation\n\nKeypairs are generated with:\n\n```shell\nfilepack keygen\n```\n\nWhich creates `master.public` and `master.private` files in the filepack\n`keychain` directory.\n\nThe `keychain` directory is located in the filepack data directory whose\nlocation is platform-dependent:\n\n| Platform | Value                                    | Example                                  |\n| -------- | ---------------------------------------- | ---------------------------------------- |\n| Linux    | `$XDG_DATA_HOME` or `$HOME`/.local/share | /home/alice/.local/share                 |\n| macOS    | `$HOME`/Library/Application Support      | /Users/Alice/Library/Application Support |\n| Windows  | `{FOLDERID_LocalAppData}`                | C:\\Users\\Alice\\AppData\\Local             |\n\n### Public Key Printing\n\nGenerated public keys can be printed with:\n\n```shell\nfilepack key\n```\n\n### Signing\n\nSignatures are created with:\n\n```shell\nfilepack sign\n```\n\nWhich signs the manifest in the current directory with your master key and adds\nthe signature to the manifest's `signatures` map. Signatures are made over a\nfingerprint hash, recursively calculated from the contents of the manifest.\n\n### Signature Verification\n\nSignatures embedded in a manifest are verified whenever a manifest is verified.\nThe presence of a signature by a particular public key can be asserted with:\n\n```sh\nfilepack verify --key PUBLIC_KEY\n```\n\nWhich will fail if a valid signature for `PUBLIC_KEY` over the manifest\ncontents is not present.\n\nFingerprints\n------------\n\nFilepack signatures are made over the manifest fingerprint hash, which is the\nroot of a Merkle tree of the files and directories contained in the manifest.\n\nFingerprints are BLAKE3 hashes, constructed such that it is impossible to\nproduce objects which are different, either in type or content, but which have\nthe same fingerprint.\n\nFingerprints may be used as a globally unique identifier. If two packages have\nthe same fingerprint, they have the same content.\n\nFor details on how fingerprints are calculated, see [DESIGN.md](DESIGN.md).\n\nWorkflows\n---------\n\n### Detecting Accidental Corruption\n\nCreate a filepack manifest with:\n\n```shell\nfilepack create \u003cPACKAGE\u003e\n```\n\nThis will create `\u003cPACKAGE\u003e/filepack.json`\n\nTo later verify the package against the manifest:\n\n```shell\nfilepack verify \u003cPACKAGE\u003e\n```\n\nBecause the manifest contains cryptographic hashes, accidental corruption to\nthe files or manifest will always be detected by `filepack verify`.\n\nThis is *not* the case with intentional, malicious corruption, since an\nattacker could modify the files and replace the manifest hashes with the hashes\nof the modified files.\n\n### Detecting Malicious Corruption\n\nBecause an attacker could modify the files and replace the manifest hashes with\nthe hashes of the modified files, you must ensure that the manifest has not\nbeen tampered with.\n\nThis can be accomplished in a number of ways, either by saving the manifest to\na secure location, saving the package fingerprint, or signing the package.\n\n#### Manifest\n\nTo save the manifest in a secure location, use the `--manifest` option to save\nthe manifest somewhere other than the package:\n\n```shell\nfilepack create \u003cPACKAGE\u003e --manifest \u003cMANIFEST\u003e\n```\n\nThen, verify the package against the saved manifest:\n\n```shell\nfilepack verify \u003cPACKAGE\u003e --manifest \u003cMANIFEST\u003e\n```\n\nBecause the manifest was protected, any modification to the package will be\ndetected. This has the advantage that not only will any modifications be\ndetected, but which files were modified can also be detected.\n\n#### Fingerprint\n\nCreate the manifest in the package root with:\n\n```shell\nfilepack create \u003cPACKAGE\u003e\n```\n\nPrint the package fingerprint:\n\n```shell\nfilepack fingerprint \u003cPACKAGE\u003e\n```\n\nSave the fingerprint in a secure location.\n\nThen, verify the package against the saved fingerprint:\n\n```sh\nfilepack verify \u003cPACKAGE\u003e --fingerprint \u003cFINGERPRINT\u003e\n```\n\nBecause the fingerprint was protected, any modification to the package will be\ndetected. This has the advantage that you only have to save a small text\nstring, but the disadvantage that while any modifications will be detected, you\nwill not be able to determine which files have changed.\n\n#### Signature\n\nCreate the manifest in the package root and sign it with your `master` key:\n\n```shell\nfilepack create \u003cPACKAGE\u003e --sign\n```\n\nThen, verify the package and its signature:\n\n```shell\nfilepack verify \u003cPACKAGE\u003e --key master\n```\n\nAny modification to the package or manifest will invalidate the signature,\nwhich will be detected. This has the advantage of not needing to save the\nmanifest or fingerprint of packages you want to verify. However, you will need\nto generate and secure your private key.\n\n### Determining Authenticity\n\nTo check the authenticity of a package created by someone else, get their\npublic key and verify that the package contains a signature by that key:\n\n```sh\nfilepack verify \u003cPACKAGE\u003e --key \u003cKEY\u003e\n```\n\nAlternatives and Prior Art\n--------------------------\n\n`filepack` serves the same purpose as programs like `shasum`, which hash files\nand output a text file containing file hashes and paths, which can later be\nused with the same program to verify that the files have not changed.\n\nThey output hashes and paths one per line, separated by whitespace, and mainly\ndiffer in which hash function they use.\n\nSome examples, with links to implementations and the hash functions they use:\n\n| binary | hash function |\n|---|---|\n| [`b2sum`](https://github.com/BLAKE2/BLAKE2) | [BLAKE2](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2) |\n| [`b3sum`](https://github.com/BLAKE3-team/BLAKE3) | [BLAKE3](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE3) |\n| [`cksfv`](https://zakalwe.fi/~shd/foss/cksfv/) | [CRC-32](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) |\n| [`hashdeep`](https://github.com/jessek/hashdeep) | various |\n| [`hashdir`](https://github.com/ultimateanu/hashdir/) | various |\n| [`sha3sum`](https://codeberg.org/maandree/sha3sum) | [SHA-3](https://en.wikipedia.org/wiki/SHA-3) |\n| [`shasum`](https://metacpan.org/pod/Digest::SHA) | [SHA-1](https://en.wikipedia.org/wiki/SHA-1) and [SHA-2](https://en.wikipedia.org/wiki/SHA-2) |\n\nCRC-32 is not a cryptographic hash function and cannot be used to detect\nintentional modifications. Similarly, SHA-1 was thought to be a cryptographic\nhash function, but is now known to be insecure.\n\n`filepack` and `b3sum` both use BLAKE3, a fast, general-purpose cryptographic\nhash function.\n\n`filepack` can also create and verify signatures. Other signing and\nverification utilities include:\n\n| binary | about |\n|---|---|\n| [`gpg`](https://gnupg.org/) | general-purpose, [OpenPGP](https://www.openpgp.org/) implementation |\n| [`ssh-keygen`](https://man.openbsd.org/ssh-keygen.1) | general-purpose, shipped with [OpenSSH](https://www.openssh.com/) |\n| [`minisign`](https://github.com/jedisct1/minisign) | general-purpose |\n| [`signifiy`]( https://github.com/aperezdc/signify) | general-purpose |\n| [`SignTool`](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool) | Windows code signing |\n| [`codesign`](https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html) | macOS code signing |\n| [`jarsigner`](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html) | JDK code signing |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcasey%2Ffilepack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcasey%2Ffilepack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcasey%2Ffilepack/lists"}