Documentation
¶
Overview ¶
Package hashset provides hash-allowlist / hash-denylist lookup for forensic and security workflows — e.g. filtering known-good files against an NSRL reference set, or flagging known-bad hashes from a threat-intel feed.
Two backing stores share one Set interface:
- in-memory (NewMemory + LoadText): three maps keyed by raw hash bytes. Fast for lists up to ~1M entries; held entirely in RAM.
- bbolt-backed (OpenBolt, built via Build): three buckets keyed by raw hash bytes. Used for NSRL-scale lists (~50M entries) where holding everything in RAM is impractical.
Lookup is O(1) for in-memory and O(log N) for bbolt — either is fast enough that allowlist filtering doesn't dominate a walk where the per-file hashing is already paid for. Supported algorithms: MD5, SHA-1, SHA-256.
Index ¶
Constants ¶
const DefaultBuildBatchSize = 50_000
DefaultBuildBatchSize is the bbolt transaction batch size. 50k rows balances commit overhead against memory usage during the build pass.
Variables ¶
var Algorithms = []string{"md5", "sha1", "sha256"}
Algorithms is the canonical set of algorithm names supported by every backing store. Other values passed to Contains return false.
var ErrInvalidHex = errors.New("invalid hex hash")
ErrInvalidHex is returned when a hex string contains non-hex characters.
var ErrSchemaMismatch = errors.New("hashset: schema version mismatch (rebuild via Build)")
ErrSchemaMismatch is returned by OpenBolt when the file's `meta/schema_version` key isn't the current "1".
var ErrUnknownAlgo = errors.New("unknown hash algorithm")
ErrUnknownAlgo is returned when a hex string's length doesn't match any supported algorithm (md5=32, sha1=40, sha256=64).
var LineLengthToAlgo = map[int]string{
32: "md5",
40: "sha1",
64: "sha256",
}
LineLengthToAlgo maps hex-string lengths back to the algorithm name. Used by the text loader to auto-detect each line's algo without explicit markers.
Functions ¶
func Build ¶
Build reads from r and writes a bbolt hashset file at outPath. Existing files are overwritten.
The output is a bbolt database with four buckets:
- md5 / sha1 / sha256 — raw 16/20/32-byte hash bytes as keys, empty values (membership is the signal).
- meta — schema_version=1.
Read via OpenBolt / Open. Single-threaded; the bottleneck on NSRL-scale input is fsync, not parse — running multiple builders in parallel doesn't help.
Types ¶
type BuildOpts ¶
type BuildOpts struct {
Format string // "text" / "nsrl" / "auto" (default "auto")
// Progress, when non-nil, is invoked roughly every BatchSize
// rows with the cumulative count read so far. Useful for
// CLI progress reporting against multi-GB NSRL drops.
Progress func(total int64)
// BatchSize controls how many rows are buffered before each
// bbolt commit. Bigger = fewer commits but bigger transactions.
// 0 → DefaultBuildBatchSize.
BatchSize int
}
BuildOpts tunes Build. Format selects how to interpret the input file: "text" for newline-separated hashes (mixed algorithms, auto-detected by length), "nsrl" for the NSRLFile.txt CSV format. "auto" (the default for the CLI) detects by inspecting the first non-blank line.
type Set ¶
Set is the read interface every hashset backing store exposes.
Contains reports whether the given hex-encoded hash (lowercase, canonical length: 32 for md5, 40 for sha1, 64 for sha256) appears in the set. Hashes of unrecognised length always return false. algo is "md5" / "sha1" / "sha256"; other values return false.
Counts returns the per-algorithm entry count snapshot, so a caller can sanity-check that a set loaded as expected.
Close releases resources (the bbolt-backed impl closes the file; in-memory is a no-op). Safe to call more than once; subsequent calls are no-ops.
func LoadText ¶
LoadText reads a newline-separated hash list from r and inserts every hash into an in-memory Set.
File format:
- One hex-encoded hash per line, mixed algorithms allowed (each line's algorithm is auto-detected by its length).
- Blank lines are ignored.
- Lines beginning with `#` are comments and ignored.
- Inline whitespace is trimmed.
- Lines that aren't blank, comments, or valid hex of a known length are rejected with an error naming the line number.
func LoadTextFile ¶
LoadTextFile opens path and calls LoadText against its contents.
func NewMemory ¶
func NewMemory() Set
NewMemory returns an empty in-memory Set. Callers populate it via LoadText (the typical entry point) or by inserting hashes through AddHex.
func Open ¶
Open auto-detects the file format: a bbolt file (with the right schema metadata) loads via OpenBolt; everything else falls through to LoadTextFile. Useful for code paths that accept either format transparently.
Detection strategy: try OpenBolt first; on ErrSchemaMismatch OR any bbolt open error, fall back to text. This catches both real text files AND bbolt files written by an incompatible version (the latter retries through text, fails clearly, and prompts a rebuild).
func OpenBolt ¶
OpenBolt opens an existing bbolt-format hashset file for read-only queries. Build the file with Build.
The file is opened in bbolt's read-only mode so queries can't accidentally mutate the set. ErrSchemaMismatch surfaces when the file's schema_version meta key doesn't match this package — protecting against future format changes.