# How Croc Handles File Metadata and Integrity Verification: A Deep Dive into the Source Code

> Explore croc's source code to understand how it verifies file integrity and handles metadata. Learn about cryptographic hashes and real-time validation for secure transfers.

- Repository: [Zack/croc](https://github.com/schollz/croc)
- Tags: deep-dive
- Published: 2026-07-26

---

**Croc ensures file integrity by computing cryptographic hashes on the sender side, embedding them in a `FileInfo` metadata structure, and validating them against real-time recomputed hashes on the receiver side after transfer.**

Croc is a secure, cross-platform file transfer tool written in Go that prioritizes data integrity alongside end-to-end encryption. Understanding how croc handles file metadata and integrity verification requires examining its core data structures and validation flows implemented in the source code.

## The FileInfo Struct: Croc's Metadata Container

Every file transfer begins with the `FileInfo` struct defined in **src/croc/croc.go**. This compact envelope captures everything needed to reconstruct a file accurately on the remote system.

The struct contains the following critical fields:

- **Name**: Base filename or directory name
- **FolderRemote** and **FolderSource**: Destination and source relative paths
- **Hash**: Cryptographic checksum of file contents
- **Size**: File size in bytes
- **ModTime**: Original modification timestamp (`time.Time`)
- **IsCompressed** and **IsEncrypted**: Boolean flags indicating transmission transformations
- **Symlink**: Target path for symbolic links

### Hash Algorithm Selection

Before transmission, the sender computes hashes using helper functions in **src/utils/utils.go**. Croc supports multiple algorithms selected by the user: `MD5HashFile`, `XXHashFile`, `IMOHashFile`, and `HighwayHashFile`. The chosen algorithm and resulting hash populate the `Hash` field before the metadata transmits to the receiver via a `TypeFileInfo` message (defined in **src/message/message.go**).

## Sender-Side Metadata Preparation

When initiating a transfer, the CLI invokes `GetFilesInfoWithExactExclusions` (**src/cli/cli.go**, lines 512-563) to walk source paths. This function constructs `FileInfo` instances for each item, computes content hashes using the selected algorithm, and packages empty directories separately for reconstruction.

```go
// CLI preparation - building file list with hashes
fi, empty, total, err := croc.GetFilesInfoWithExactExclusions(
    []string{"mydir/"}, false, true, []string{}, []string{})
if err != nil { log.Fatal(err) }

client := croc.NewClient(opts)          // opts includes HashAlgorithm = "md5"
client.Send(fi, empty, total)          // metadata (including hash) is sent automatically

```

## Receiver-Side Validation and Security

Upon receiving metadata, croc immediately validates incoming data to prevent directory traversal attacks and ensure completeness. The validation logic in **src/croc/croc.go** (lines 674-690) performs three critical checks:

1.  Rejects paths containing `".."` components that would escape the receive directory
2.  Discards empty-folder metadata that would resolve outside the intended destination
3.  Ensures required fields (`Name`, `Size`, `Hash`) are present and non-empty

These checks run before any file data transfers, protecting the receiver's filesystem from hostile metadata.

## Real-Time Integrity Verification During Transfer

During the actual file transfer, integrity verification happens concurrently with the download. The receiver streams bytes to disk while recomputing the hash using the same algorithm advertised by the sender. After the final byte writes, croc compares the computed hash against the metadata hash at lines 2590-2608:

```go
// Inside client.processMessageFileInfo (receiver)
computedHash, err := utils.HashFile(pathToTmp, fileInfo.HashAlgorithm)
if err != nil { return false, err }

if !bytes.Equal(fileInfo.Hash, computedHash) {
    return false, fmt.Errorf("hash mismatch for %s", fileInfo.Name)
}
os.Chtimes(filepath.Join(fileInfo.FolderRemote, fileInfo.Name),
            fileInfo.ModTime, fileInfo.ModTime)

```

If `bytes.Equal` returns false, the transfer aborts immediately with a hash mismatch error. This mechanism catches corruption from network errors, storage failures, or malicious tampering.

### Handling Compressed and Encrypted Files

For compressed or encrypted transfers, croc computes and verifies hashes **after** applying these transformations. This validates the exact byte stream written to disk, ensuring end-to-end integrity of the transmitted data rather than the original uncompressed content.

## Preserving File Attributes After Verification

Successful transfers preserve original metadata using `os.Chtimes` (**src/croc/croc.go**, lines 2655-2659). The receiver applies the `ModTime` from the `FileInfo` struct to the newly written file, maintaining accurate timestamps across systems. This occurs only after the hash verification succeeds, ensuring corrupted files never receive authentic metadata.

## Summary

- Croc uses the `FileInfo` struct in **src/croc/croc.go** to encapsulate file metadata including cryptographic hashes, paths, and timestamps
- Senders compute hashes using MD5, xxhash, imohash, or highwayhash via helper functions in **src/utils/utils.go**
- The receiver validates metadata using security checks at lines 674-690 to prevent directory traversal and ensure required fields exist
- Integrity verification occurs during download with final comparison at lines 2590-2608, aborting on any hash mismatch
- Original modification times are preserved using `os.Chtimes` only after successful verification

## Frequently Asked Questions

### What hash algorithms does croc support for integrity verification?

Croc supports four cryptographic hash functions: MD5, xxhash, imohash, and highwayhash. The sender selects the algorithm during transfer initiation via configuration options, and both sides use the same method for valid comparison. These implementations reside in **src/utils/utils.go**.

### How does croc prevent directory traversal attacks via metadata?

Croc inspects incoming `FileInfo` paths in **src/croc/croc.go** (lines 674-690) and rejects any containing `".."` components or paths that would resolve outside the designated receive directory. Test cases in **src/croc/croc_test.go** verify that hostile metadata triggers appropriate errors without touching the filesystem.

### Does croc verify integrity before or after compression and encryption?

Croc computes and verifies hashes **after** compression and encryption are applied. This ensures the integrity check validates the exact byte stream transmitted over the network and written to disk, guaranteeing end-to-end integrity of the actual transferred payload.

### What happens if a file fails the hash verification check?

If the recomputed hash does not match the metadata hash at lines 2590-2608, croc immediately aborts the transfer and returns a hash mismatch error. The partially downloaded file is discarded, preventing corrupted data from being committed to the filesystem or retaining incorrect timestamps.