Documentation
¶
Overview ¶
Package pidchain produces SHA256 fingerprints identifying local process callers, for same-host IPC authentication without stored credentials.
The consumer obtains a peer PID from the kernel and calls Fingerprint with it. The returned string identifies the caller's full process ancestry; identical ancestry produces an identical fingerprint. Callers store the fingerprint as the verification value in their own authentication record. On every inbound call, the consumer re-derives the fingerprint from kernel state and compares it against the stored value.
Identity comes from a fresh kernel query per call. Nothing secret is stored on the client, nothing is transmitted by the client. The credential cannot be stolen because the credential does not exist at rest. This addresses the cleartext-credential pattern described by CWE-312, CWE-313, CWE-522, CWE-256, and CWE-922.
Supported platforms ¶
pidchain supports macOS and Windows. Linux and other platforms compile but return ErrPlatformUnsupported at runtime.
Concurrency ¶
Both Fingerprint and Chain do a fresh kernel walk on every call. The package holds no state and is safe for concurrent use from multiple goroutines.
Package pidchain returns kernel-attested process ancestry and a stable fingerprint over the ancestors' code-signing identities. Use Fingerprint for runtime authentication; use Chain for diagnostics and UI.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrPlatformUnsupported = walker.ErrPlatformUnsupported ErrProcessDead = walker.ErrProcessDead )
Error sentinels re-exported from internal/walker so consumers can write errors.Is(err, pidchain.ErrProcessDead).
Functions ¶
func Fingerprint ¶
Fingerprint returns a lowercase hex SHA256 over the code-signing identity of every ancestor of pid. Deterministic: identical ancestry produces an identical fingerprint. Any change to any ancestor's signing identity produces a different fingerprint.
Example ¶
ExampleFingerprint demonstrates the typical server-side usage: obtain the peer PID via a kernel-attested mechanism, derive the fingerprint, compare against an ACL.
package main
import (
"os"
"github.com/jwyattgh/pidchain"
)
func main() {
// In a real server, peerPID comes from the kernel — cmd.Process.Pid
// for a spawned child, LOCAL_PEERPID for a UDS peer, etc. Here we
// use the current process for illustration.
peerPID := os.Getpid()
fp, err := pidchain.Fingerprint(peerPID)
if err != nil {
// errors.Is(err, pidchain.ErrProcessDead),
// errors.Is(err, pidchain.ErrPlatformUnsupported)
_ = err
return
}
// fp is a 64-character lowercase hex SHA256.
_ = fp
}
Output:
Types ¶
type ProcessChain ¶
type ProcessChain = walker.ProcessChain
ProcessChain is the walked ancestry plus the SHA256 fingerprint over every entry's code-signing identity.
func Chain ¶
func Chain(pid int) (ProcessChain, error)
Chain returns the walked ancestry as structured data. Intended for diagnostics, setup-time UI, and pairing prompts. Not for runtime authentication — use Fingerprint.
Example ¶
ExampleChain demonstrates the diagnostic / pairing-prompt usage: get the structured ancestor list to display to a human (or to log) before committing to store the corresponding fingerprint.
package main
import (
"os"
"github.com/jwyattgh/pidchain"
)
func main() {
chain, err := pidchain.Chain(os.Getpid())
if err != nil {
_ = err
return
}
// chain.Entries is the ordered ancestry, queried PID first.
// chain.Fingerprint is the same value Fingerprint() would return.
for _, e := range chain.Entries {
_ = e.BinaryPath
_ = e.TeamID
_ = e.BundleIdentifier
_ = e.AuthorityLeaf
}
}
Output:
type ProcessInfo ¶
type ProcessInfo = walker.ProcessInfo
ProcessInfo is one ancestor's kernel-attested identity.