Help us shape the future of Go! Take the 2026 Go Developer Survey

clientbuildtest

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2026 License: GPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package clientbuildtest builds the fixtures the client-building tests need: a file shaped like a Windows executable, with a reserved region inside it.

It is a fixture and not a real client on purpose. A real one is eleven megabytes of another repository's build output, which no test in this one can produce; this is a few kilobytes, it is deterministic, a test can put the region anywhere inside it, and debug/pe parses it. The real article is exercised end to end against a client built by wails3.

The layout below is spelled out from the format in the package comment of clientbuild rather than imported from it. A fixture that reused the code under test could only ever prove that code agrees with itself, and the client at the other end of this format has its own, separate implementation of exactly these offsets.

Index

Constants

View Source
const (
	// RegionSize is the whole reserved region.
	RegionSize = 1024
	// MarkerSize is the length of each marker.
	MarkerSize = 16
	// OffVersion, OffReserved, OffLength, OffChecksum and OffPayload are the
	// header fields between the head marker and the payload.
	OffVersion  = 16
	OffReserved = 17
	OffLength   = 18
	OffChecksum = 20
	OffPayload  = 24
	// OffTail is where the tail marker starts.
	OffTail = RegionSize - MarkerSize
	// Version1 is the format version a stamped region carries.
	Version1 = 1
)

The region, as the format describes it.

View Source
const FileAlignment = 0x200

FileAlignment is what a section's bytes on disk are rounded up to. It is the smallest value a PE may declare, which keeps the fixture small.

View Source
const TestKeyBits = 2048

TestKeyBits is the RSA key size the fixtures use. It is small on purpose: these keys sign a fixture and are thrown away at the end of the test, and three thousand bits would put a second on every run that uses one.

Variables

This section is empty.

Functions

func BlankRegion

func BlankRegion() []byte

BlankRegion is the region as a prebuilt client carries it: the two markers, and room between them.

func Certificate

func Certificate(tb testing.TB, opts CertificateOptions) ([]byte, *x509.Certificate)

Certificate mints a certificate and returns the PKCS#12 file holding it and its key — the file an operator uploads — along with the certificate itself for a test that wants to assert about what is inside.

func Client

func Client(region []byte) []byte

Client is a fixture client: filler, a region, more filler, all inside a PE. The filler is there so that a test asserting "nothing outside the region changed" has something outside the region to assert about.

func Ed25519Certificate

func Ed25519Certificate(tb testing.TB) []byte

Ed25519Certificate is a certificate holding a key that is fine everywhere except here: Authenticode names RSA and ECDSA and nothing else, so a server that accepted one would make signatures no Windows machine can check.

func Head() []byte

Head is the marker that opens the region.

func Install

func Install(tb testing.TB) string

Install writes a stampable client into a directory of its own and returns its path, which is what a test wanting "a server that has a client" needs.

func MultiSectionPE

func MultiSectionPE(region []byte) []byte

MultiSectionPE is a fixture shaped more like a real client than PE is: several sections, and debug data after the last of them that belongs to no section at all.

Both of those are places the Authenticode hash can go wrong in a way one section cannot show: the sections have to be hashed one after another with their alignment padding, and the bytes after the last of them have to be hashed too — leaving them out would let somebody append to a signed file without breaking the signature.

The section table is written in file order, which is what every linker does. ShuffleSectionTable makes one that is not, for the test that the hash follows the file rather than the table.

func PE

func PE(body []byte) []byte

PE wraps bytes in the smallest thing that is a valid Windows executable: a DOS header, a PE header, one section, and the bytes as that section's data, padded out to the alignment the header declares.

func ShuffleSectionTable

func ShuffleSectionTable(body []byte) []byte

ShuffleSectionTable reverses the order of the rows in a PE's section table, leaving every other byte of the file alone.

The file it returns is the same program: the sections are where they were and hold what they held, and only the order they are listed in has changed. The Authenticode hash is defined over the sections in the order they sit in the file, so a signature over this file and a signature over the original must be the same signature. A hash that read the table in order instead would produce a different one, and that is what the test using this catches.

func StampedRegion

func StampedRegion(payload string) []byte

StampedRegion is a region with a payload written into it by hand, which is how the tests build the cases that are wrong in one specific way: take this, and break one field of it.

func Tail

func Tail() []byte

Tail is the marker that closes it.

func WriteAt

func WriteAt(tb testing.TB, path string, body []byte) string

WriteAt puts a fixture on the disk and returns its path.

Types

type Authority

type Authority struct {
	Certificate *x509.Certificate
	Key         *rsa.PrivateKey
}

Authority is a certificate authority the fixtures can issue under, for the tests that care about the difference between a certificate an operator issued to themselves and one issued to them.

func NewAuthority

func NewAuthority(tb testing.TB, name string) *Authority

NewAuthority mints a certificate authority.

type CertificateOptions

type CertificateOptions struct {
	// CommonName is who the certificate says signed. Empty is a usable
	// default rather than a certificate with no name.
	CommonName string
	// NotBefore and NotAfter are its window. Zero values are an hour ago and a
	// year from now.
	NotBefore, NotAfter time.Time
	// NoCodeSigning mints one without the extended key usage that marks it for
	// signing software — the certificate an operator exports from the wrong
	// place, which signs fine and which Windows refuses.
	NoCodeSigning bool
	// ECDSA mints an elliptic-curve key instead of RSA.
	ECDSA bool
	// Issuer is the authority to issue under. Nil is self-signed, which is
	// what an operator making their own certificate has.
	Issuer *Authority
	// Password is what the PKCS#12 file is locked with.
	Password string
}

CertificateOptions is what to mint. The zero value is a plain self-signed code-signing certificate that is valid now, which is what most tests want.

Jump to

Keyboard shortcuts

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