pacs

package
v0.580.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 6, 2026 License: AGPL-3.0 Imports: 3 Imported by: 0

Documentation

Overview

Package pacs decodes Physical Access Control System (PACS) credential payloads — the upper-layer encoding that sits on top of the Wiegand bit-stream produced by an HID Prox / iCLASS / EM-style reader.

Wrap-vs-native judgement

Native. The HID format catalogue is fully public via the
HID OEM-format spec sheets, the Proxmark3 Iceman codebase
(`hidpacs.go` table), and decades of community
reverse-engineering. Each format is a small fixed-width
bit-field layout with one or more parity bits — pure
bit-twiddling, no crypto, no state. Operators feed the
raw bit string that drops out of `wiegand_decode` (or a
proxmark3 lf hid demod) and get the documented
facility-code / card-number / OEM-code fields plus a
parity-validity check.

What this package covers

  • Input convention: a bit string ("0"/"1" only) of one of the recognised widths. Hex+bit-length input is also accepted for convenience (hex is left-aligned into a bit buffer of exactly the declared width, MSB first).

  • Recognised formats and their wire layouts:

  • **HID H10301 26-bit** — the canonical HID Prox format. P + 8 FC + 16 CN + P. Bit 0 is even parity over bits 1-12; bit 25 is odd parity over bits 13-24.

  • **HID H10306 34-bit** — extended FC range. P + 16 FC

  • 16 CN + P. Bit 0 is even parity over bits 1-16; bit 33 is odd parity over bits 17-32.

  • **HID H10304 37-bit** — wide CN. P + 16 FC + 19 CN + P. Bit 0 is even parity over bits 1-18; bit 36 is odd parity over bits 18-35.

  • **HID H10302 37-bit** — no FC, 35-bit CN. P + 35 CN + P. Bit 0 is even parity over bits 1-18; bit 36 is odd parity over bits 18-35.

  • **HID Corporate 1000 35-bit** — proprietary. 2 leading parity bits (even/odd over a complex bit pattern per HID OEM spec) + 12 FC + 20 CN + trailing parity.

  • **HID Corporate 1000 48-bit** — extended variant. 2 parity bits + 22 FC + 23 CN + trailing parity.

  • When the input length matches a single recognised format, the decoder returns that format. When the length matches multiple formats (e.g. 37-bit could be H10304 OR H10302), the decoder returns all candidates and lets the caller pick by parity-validity or by facility-code sanity.

  • Parity is computed and surfaced as parity_valid bool for each candidate. A failed parity bit doesn't suppress the candidate (the bit-pattern is still useful for debugging) but is clearly flagged.

What this package does NOT cover (deliberately out of scope)

  • The reader-layer Wiegand bit-stream extraction — `wiegand_decode` already handles that.

  • The crypto layer of iCLASS Standard or Elite (3DES key diversification, MAC validation) — payload-level decryption is a separate Spec.

  • DESFire AID / EV1 application records — those are NFC APDU exchanges decoded by `desfire_decode`.

  • LF / EM4xxx baseband modulation (Manchester / biphase) — `em4100_decode` handles EM-style baseband.

  • Cardholder-database lookup — facility-code / card-number to "who owns this badge" mapping is the operator's job (the PACS database is external).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EncodeWiegand added in v0.376.0

func EncodeWiegand(format string, facilityCode, cardNumber uint64) (string, error)

EncodeWiegand builds the raw Wiegand bit-string for a named HID format from a facility code + card number — the inverse of DecodeBits. The result is the exact frame DecodeBits parses back (round-trip verified): leading even-parity bit, the BCD-less binary FC + CN fields, and the trailing odd-parity bit, MSB-first.

Wrap-vs-native judgement

Native, and the inverse of the existing decoder. HID Wiegand formats are public, fixed-width bit layouts with parity — pure bit-twiddling, no crypto, no state, no hardware. Generation only: this produces the bits an operator would write to a T5577/emulate; it performs no write or TX, so it carries the same Low risk as the decoder. Correctness is verifiable three ways: round-trip against DecodeBits, hand-computed parity vectors, and the published HID format layouts.

Covered formats (clean, non-overlapping parity — hand-verifiable)

  • "H10301" — 26-bit: even parity + 8-bit FC + 16-bit CN + odd parity. Even parity over the top 12 data bits, odd over the bottom 12.
  • "H10306" — 34-bit: even parity + 16-bit FC + 16-bit CN + odd parity. Even parity over the FC, odd over the CN.
  • "H10304" — 37-bit: even parity + 16-bit FC + 19-bit CN + odd parity. Even parity over the top 18 data bits, odd over the bottom 18 (the two ranges overlap at the 18th bit — both are still clean functions of the data, so the frame round-trips parity-valid).
  • "H10302" — 37-bit, no facility code: even parity + 35-bit CN + odd parity. Identical parity ranges to H10304; pass facility code 0.

Deliberately deferred

The HID Corporate 1000 (35/48-bit) formats use a self-referential / proprietary parity scheme that the decoder validates only best-effort (the parity bits fall inside their own coverage range). Encoding them to a guaranteed-valid frame is not reliable without an external reference vector, so they are not offered here (decode still surfaces them as candidates).

Types

type Candidate

type Candidate struct {
	Format       string `json:"format"`
	Spec         string `json:"spec_summary"`
	FacilityCode uint64 `json:"facility_code,omitempty"`
	CardNumber   uint64 `json:"card_number"`
	OEMCode      uint64 `json:"oem_code,omitempty"`
	Issue        uint64 `json:"issue_code,omitempty"`
	ParityValid  bool   `json:"parity_valid"`
	ParityNotes  string `json:"parity_notes,omitempty"`
}

Candidate is one decoded PACS format interpretation.

type Result

type Result struct {
	BitLength  int         `json:"bit_length"`
	BitsRaw    string      `json:"bits_raw"`
	HexLeft    string      `json:"hex_msb_first"`
	Candidates []Candidate `json:"candidates"`
	Notes      []string    `json:"notes,omitempty"`
}

Result is the top-level decoded view.

func DecodeBits

func DecodeBits(bits string) (*Result, error)

DecodeBits parses a bit-string PACS payload.

func DecodeHex

func DecodeHex(hexStr string, bitLen int) (*Result, error)

DecodeHex parses a hex-encoded PACS payload with a declared bit count. The hex bytes are left-aligned into a bit buffer of exactly bitLen bits (MSB first). Unused trailing bits in the last byte are silently discarded; callers are expected to provide a bitLen consistent with what `wiegand_decode` or the reader actually emitted.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL