Documentation
¶
Overview ¶
Package authenticode implements Microsoft Authenticode PE signing in pure Go. It computes the Authenticode digest, builds the CMS SignedData (with SpcIndirectDataContent), embeds an RFC3161 timestamp, and writes the resulting WIN_CERTIFICATE into the PE's attribute certificate table. It signs through any crypto.Signer (e.g. the github.com/KarpelesLab/hsm IDPrime backend driving a USB token).
Index ¶
- func BuildSignedData(spc []byte, signer crypto.Signer, chain []*x509.Certificate, opts SignOptions) ([]byte, error)
- func BuildSpcIndirectDataContent(peDigest []byte, h crypto.Hash) ([]byte, error)
- func RequestTimestamp(ctx context.Context, tsaURL string, signature []byte, h crypto.Hash) ([]byte, error)
- func Sign(pe []byte, signer Signer, opts SignOptions) ([]byte, error)
- func SignWithChain(pe []byte, signer crypto.Signer, chain []*x509.Certificate, opts SignOptions) ([]byte, error)
- type PE
- type SignOptions
- type Signer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildSignedData ¶
func BuildSignedData(spc []byte, signer crypto.Signer, chain []*x509.Certificate, opts SignOptions) ([]byte, error)
BuildSignedData assembles a complete CMS SignedData ContentInfo around the supplied SpcIndirectDataContent. The signing key is driven through the standard crypto.Signer interface — pass an idprime.Signer (or any other implementation) and the resulting SignedData carries an ECDSA signature ready for embedding in a PE.
chain must start with the leaf certificate that matches signer's public key; subsequent entries (intermediates) are embedded as-is.
If opts.TSAURL is set, an RFC 3161 timestamp is fetched and embedded as an unsigned attribute on the SignerInfo.
func BuildSpcIndirectDataContent ¶
BuildSpcIndirectDataContent builds the SpcIndirectDataContent payload that goes into the eContent field of the signed CMS ContentInfo. peDigest is the Authenticode digest of the PE image (the bytes produced by PE.AuthenticodeDigest), and h is the hash algorithm used to compute it.
func RequestTimestamp ¶
func RequestTimestamp(ctx context.Context, tsaURL string, signature []byte, h crypto.Hash) ([]byte, error)
RequestTimestamp asks an RFC 3161 Time-Stamp Authority to timestamp the given signature bytes. It returns the raw TimeStampToken (a CMS ContentInfo) ready for embedding as the value of the SPC_RFC3161_OBJID (1.3.6.1.4.1.311.3.3.1) unsigned attribute on a SignerInfo — the Microsoft-Authenticode-specific carrier that signtool / osslsigncode actually parse.
The TSA URL must accept POSTs with Content-Type application/timestamp-query (the standard).
func Sign ¶
func Sign(pe []byte, signer Signer, opts SignOptions) ([]byte, error)
Sign produces a Microsoft Authenticode signature over the given PE image, embeds it as a WIN_CERTIFICATE in the file, and returns the new bytes. The signing key + cert chain are supplied through Signer. If opts.TSAURL is set, an RFC 3161 timestamp from that authority is fetched and embedded in the SignerInfo's unsigned attributes.
The input slice is not modified.
func SignWithChain ¶
func SignWithChain(pe []byte, signer crypto.Signer, chain []*x509.Certificate, opts SignOptions) ([]byte, error)
SignWithChain is the lower-level entry point: pass a raw crypto.Signer plus the certificate chain explicitly (leaf first). Useful when the chain comes from somewhere other than the Signer.
Types ¶
type PE ¶
type PE struct {
// contains filtered or unexported fields
}
PE represents a parsed PE32 / PE32+ image and remembers the offsets the Authenticode hash algorithm needs to skip.
func Parse ¶
Parse parses a PE32 or PE32+ image and locates the offsets used by Authenticode hashing. Does not modify the input slice.
func (*PE) AuthenticodeDigest ¶
AuthenticodeDigest computes the Microsoft Authenticode hash over the PE image, omitting the four-byte file checksum, the eight-byte attribute-certificate-table data-directory entry, and any existing attribute certificate table contents.
All offsets are clamped to [0, len(raw)] before slicing so a malformed PE that survived Parse cannot panic here.
func (*PE) EmbedSignature ¶
EmbedSignature returns a copy of the PE with the given CMS SignedData blob embedded as a WIN_CERTIFICATE in a new attribute certificate table appended to the file. The data-directory entry is updated accordingly.
Any pre-existing attribute certificate table is replaced.
type SignOptions ¶
type SignOptions struct {
// Hash selects the digest algorithm used for both the
// SpcIndirectDataContent's messageDigest and the SignerInfo's
// signed-attrs hash. Defaults to crypto.SHA256.
Hash crypto.Hash
// TSAURL, if non-empty, requests an RFC 3161 timestamp from the
// given Time-Stamp Authority over HTTP and embeds the resulting
// token under SPC_RFC3161_OBJID (1.3.6.1.4.1.311.3.3.1) in the
// SignerInfo's unsigned attributes — the OID Authenticode
// verifiers (signtool, osslsigncode) look up.
TSAURL string
// Context governs the TSA HTTP call. Defaults to
// context.Background().
Context context.Context
// SigningTime overrides the PKCS#9 signingTime attribute. Zero
// (the default) means time.Now() at signing — which is what
// signtool / osslsigncode do. Set explicitly only for reproducible
// builds or tests.
SigningTime time.Time
// ProgramName and ProgramURL populate the SpcSpOpusInfo signed
// attribute (signtool's "/d <name>" / "/du <url>"; osslsigncode's
// "-n <name>" / "-i <url>"). If both are empty the attribute is
// omitted entirely, matching osslsigncode's behavior — verifiers
// surface them as the publisher's display name / "more info" link.
ProgramName string
ProgramURL string
}
SignOptions configures the CMS signing operation.
type Signer ¶
type Signer interface {
crypto.Signer
Certificate() *x509.Certificate
CertificateChain() []*x509.Certificate
}
Signer is a signing key bundled with the certificate (and the rest of the chain) that asserts its public key. hsm.Key from github.com/KarpelesLab/hsm v0.2.5+ satisfies it directly — an IDPrime smart-card key plugs in without conversion.
CertificateChain must return the chain leaf-first; intermediates and (optionally) the root follow. When the slice is empty Sign falls back to Certificate() and signs with a single-element chain.