sshpub

package
v0.685.0 Latest Latest
Warning

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

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

Documentation

Overview

Package sshpub triages OpenSSH *public* keys — the authorized_keys / known_hosts / bare public-key lines an operator finds on a host during IR or an audit. It is the public-key counterpart to the private-key decoders (ssh_privkey_decode, pem_privkey_decode, putty_privkey_decode): given a line (or a whole file of lines), it reports per key the type, key size, and the SHA256 + MD5 fingerprints exactly as `ssh-keygen -l` prints them, plus the comment, any authorized_keys options, and any known_hosts marker / host field.

Two forensic levers beyond plain parsing:

  • For an ssh-rsa key it surfaces the modulus (hex) so the key chains straight into roca_detect — fingerprint the key, then screen the RSA ones for the Infineon ROCA weakness.
  • For a hashed known_hosts entry (|1|salt|hash) it can test a candidate hostname against the HMAC-SHA1, deanonymising which host the entry refers to — the same check `ssh-keygen -F` performs, the standard technique for mapping lateral movement off a captured known_hosts file.

Wrap-vs-native: native — the public-key wire blob is parsed directly off the RFC 4253 length-prefixed format (a sequence of uint32-prefixed strings) and the fingerprints are stdlib crypto/sha256 + crypto/md5 + crypto/hmac over that blob. No x/crypto/ssh dependency (and so none of its govulncheck surface) and no new go.mod entry. The fingerprint, key-size, and hashed-host computations are pinned against `ssh-keygen -l` / `-H` / `-F`.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Key

type Key struct {
	// Type is the declared/embedded key algorithm, e.g. "ssh-ed25519",
	// "ssh-rsa", "ecdsa-sha2-nistp256", "ssh-dss",
	// "sk-ssh-ed25519@openssh.com".
	Type string `json:"type"`
	// Label is the friendly type ssh-keygen prints in parentheses
	// (ED25519 / RSA / ECDSA / DSA / ED25519-SK / ECDSA-SK).
	Label string `json:"label"`
	// Bits is the key size as ssh-keygen reports it.
	Bits int `json:"bits"`
	// FingerprintSHA256 is "SHA256:" + base64(SHA-256(blob)) without padding.
	FingerprintSHA256 string `json:"fingerprint_sha256"`
	// FingerprintMD5 is "MD5:" + colon-separated lowercase hex of MD5(blob).
	FingerprintMD5 string `json:"fingerprint_md5"`
	// Comment is the trailing comment field, if any.
	Comment string `json:"comment,omitempty"`
	// Options is the authorized_keys options field, when the prefix parsed as
	// options (contained "=" or a known option keyword).
	Options string `json:"options,omitempty"`
	// Marker is a known_hosts marker: "@cert-authority" or "@revoked".
	Marker string `json:"marker,omitempty"`
	// Hosts is the known_hosts host field (raw — may be a comma list, a
	// [host]:port form, or a |1|salt|hash hashed entry).
	Hosts string `json:"hosts,omitempty"`
	// HashedHost is true when Hosts is a |1|salt|hash hashed known_hosts entry.
	HashedHost bool `json:"hashed_host,omitempty"`
	// HostMatch is set to the candidate hostname when it was supplied and
	// matched this entry's host field (hashed via HMAC-SHA1, or plaintext).
	HostMatch string `json:"host_match,omitempty"`
	// RSAModulusHex is the ssh-rsa modulus in hex, for chaining into
	// roca_detect. Empty for non-RSA keys.
	RSAModulusHex string `json:"rsa_modulus_hex,omitempty"`
	// Note carries interpretation guidance (weak key size, ROCA chaining, …).
	Note string `json:"note,omitempty"`
}

Key is one parsed public-key entry.

type Result

type Result struct {
	// Keys is one entry per parsed line.
	Keys []Key `json:"keys"`
	// Count is len(Keys).
	Count int `json:"count"`
}

Result is the outcome of a Decode call.

func Decode

func Decode(input, candidateHost string) (*Result, error)

Decode parses one or many OpenSSH public-key lines (newline-separated). candidateHost, when non-empty, is tested against each entry's host field — matching hashed (|1|salt|hash) entries via HMAC-SHA1 and plaintext host lists directly. Blank lines and #-comments are skipped. A line that does not parse is reported as a Key with a Note rather than aborting the whole batch.

Jump to

Keyboard shortcuts

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