Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ jobs:
run: |
cargo build --release --target ${{ matrix.target }} -p pcf-debug
cargo build --release --target ${{ matrix.target }} -p pcf-compact
cargo build --release --target ${{ matrix.target }} -p pcf-sig-cli --bin pcf-sig
cargo build --release --target ${{ matrix.target }} -p pfs-ms --bin pfs

- name: Build (macOS universal2)
Expand All @@ -97,6 +98,7 @@ jobs:
for t in ${{ matrix.macos-targets }}; do
cargo build --release --target "$t" -p pcf-debug
cargo build --release --target "$t" -p pcf-compact
cargo build --release --target "$t" -p pcf-sig-cli --bin pcf-sig
cargo build --release --target "$t" -p pfs-ms --bin pfs
done
mkdir -p target/universal2-apple-darwin/release
Expand All @@ -106,11 +108,15 @@ jobs:
lipo -create -output target/universal2-apple-darwin/release/pcf-compact \
target/x86_64-apple-darwin/release/pcf-compact \
target/aarch64-apple-darwin/release/pcf-compact
lipo -create -output target/universal2-apple-darwin/release/pcf-sig \
target/x86_64-apple-darwin/release/pcf-sig \
target/aarch64-apple-darwin/release/pcf-sig
lipo -create -output target/universal2-apple-darwin/release/pfs \
target/x86_64-apple-darwin/release/pfs \
target/aarch64-apple-darwin/release/pfs
file target/universal2-apple-darwin/release/pcf-debug
file target/universal2-apple-darwin/release/pcf-compact
file target/universal2-apple-darwin/release/pcf-sig
file target/universal2-apple-darwin/release/pfs

- name: Stage and archive (unix)
Expand All @@ -120,7 +126,7 @@ jobs:
VERSION='${{ needs.resolve-version.outputs.version }}'
TARGET='${{ matrix.target }}'
mkdir -p staging
for bin in pcf-debug pcf-compact pfs; do
for bin in pcf-debug pcf-compact pcf-sig pfs; do
STAGE="staging/${bin}-${VERSION}-${TARGET}"
mkdir -p "$STAGE"
cp "target/${TARGET}/release/${bin}" "$STAGE/${bin}"
Expand All @@ -136,7 +142,7 @@ jobs:
$version = '${{ needs.resolve-version.outputs.version }}'
$target = '${{ matrix.target }}'
New-Item -ItemType Directory -Force staging | Out-Null
foreach ($bin in @('pcf-debug', 'pcf-compact', 'pfs')) {
foreach ($bin in @('pcf-debug', 'pcf-compact', 'pcf-sig', 'pfs')) {
$stage = "staging/$bin-$version-$target"
New-Item -ItemType Directory -Force $stage | Out-Null
Copy-Item "target/$target/release/$bin.exe" "$stage/$bin.exe"
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/ci-pcf-sig.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI / Rust (pcf-sig CLI)

on:
push:
branches: [master]
pull_request:
branches: [master]

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"

defaults:
run:
working-directory: tools/pcf-sig

jobs:
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check

clippy:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: tools/pcf-sig
- run: cargo clippy --all-targets --all-features -- -D warnings

test:
name: test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: tools/pcf-sig
- run: cargo build --verbose
- run: cargo test --all-targets --verbose
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ members = [
"reference/PCF-SIG-v1.0",
"tools/pcf-debug",
"tools/pcf-compact",
"tools/pcf-sig",
]
16 changes: 16 additions & 0 deletions reference/PCF-SIG-v1.0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ for report in verify_all_with_recheck(&mut c)? {
# Ok::<(), pcf_sig::Error>(())
```

## Command-line tool

A ready-made CLI lives in [`tools/pcf-sig`](../../tools/pcf-sig) (`pcf-sig`),
built on this crate:

```sh
pcf-sig keygen id.key id.pub # 32-byte raw Ed25519 seed + public key
pcf-sig sign file.pcf --key id.key # incremental by default; --resign to redo
pcf-sig verify file.pcf --key id.pub # per-signature / per-partition report
pcf-sig keys file.pcf # list embedded PCFSIG_KEY fingerprints
```

A PFS-MS archive is a PCF file, so `pcf-sig verify`/`keys` work on it directly;
to *sign* a PFS-MS file use `pfs sign`, which commits the signature as a PFS
session (see [`reference/PFS-MS-v1.0`](../PFS-MS-v1.0)).

## Trust patterns

The profile describes one non-X.509 way for an application to express trust
Expand Down
10 changes: 10 additions & 0 deletions reference/PFS-MS-v1.0/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,13 @@ flate2 = { version = "1", default-features = false, features = ["rust_backend"]

# Portable file modification-time setting for the directory-import/extract tools.
filetime = "0.2"

# Shared PCF-SIG command-line logic, so `pfs` can run keygen / verify-sig using
# exactly the same implementation as the standalone `pcf-sig` tool.
pcf-sig-cli = { path = "../../tools/pcf-sig", version = "0.0.8" }

# The PCF-SIG signing primitives. Signing a PFS-MS file cannot simply append
# partitions (that would break the backward-linked session chain); instead the
# PCFSIG_KEY / PCFSIG_SIG partitions are committed as a dedicated PFS session
# (see `src/sign.rs`), built from these primitives.
pcf-sig = { path = "../PCF-SIG-v1.0", version = "0.0.8" }
31 changes: 31 additions & 0 deletions reference/PFS-MS-v1.0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,37 @@ on extract; pass `--no-metadata` (on either side) to skip this, and `--store` to
disable compression. Symlinks and other non-regular files are skipped with a
warning.

### Signing (PCF-SIG)

`pfs` can sign archives with [PCF-SIG](../PCF-SIG-v1.0) (Ed25519). Because
PFS-MS is append-only with a backward-linked session chain, a signature is
**committed as its own PFS session** carrying the `PCFSIG_KEY` / `PCFSIG_SIG`
partitions — not appended out of band — so `verify` keeps working.

```
# Generate a keypair (delegates to the pcf-sig tool).
cargo run --bin pfs -- keygen id.key id.pub

# Sign content + node records not yet signed by this key (incremental).
cargo run --bin pfs -- sign fs.pfs --key id.key # no-op if nothing new
cargo run --bin pfs -- sign fs.pfs --key id.key --resign # re-sign everything

# Verify embedded signatures (optionally assert a trusted public key).
cargo run --bin pfs -- verify-sig fs.pfs --key id.pub
```

Every mutating command (`mkfs`, `mkdir`, `put`, `mv`, `rm`, `create`, `update`)
also accepts `--key <priv>` to **auto-sign** right after its commit, so each
operation adds one signature covering just the partitions it introduced:

```
cargo run --bin pfs -- mkfs fs.pfs --key id.key
echo hi | cargo run --bin pfs -- put fs.pfs hello.txt - --key id.key
```

Signatures cover file content and node records; PFS-MS's own inter-session hash
chain (checked by `verify`) already makes session records tamper-evident.

## Layout

```
Expand Down
Loading
Loading