From cb41b3248cd4973148b7c9d59231575689c9778f Mon Sep 17 00:00:00 2001 From: George Adams Date: Thu, 4 Jun 2026 15:31:37 +0100 Subject: [PATCH 1/2] Change PGP signature file extension from .sig to .asc Align with upstream Go's convention of using .asc for detached PGP signature files. Fixes https://github.com/microsoft/go/issues/181. - sign tool: Always produce .asc, additionally produce .sig for go1.26 and earlier for backward compatibility - sign tool: Test mode handles both .asc and .sig files - updatelinktable: Use .asc as signature suffix for all versions --- eng/_util/cmd/sign/archive.go | 42 ++++++++++++++----- eng/_util/cmd/sign/sign.go | 2 +- .../cmd/updatelinktable/updatelinktable.go | 2 +- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/eng/_util/cmd/sign/archive.go b/eng/_util/cmd/sign/archive.go index b76451d3c6b..1da9dc52b09 100644 --- a/eng/_util/cmd/sign/archive.go +++ b/eng/_util/cmd/sign/archive.go @@ -16,6 +16,7 @@ import ( "log" "os" "path/filepath" + "strconv" "strings" ) @@ -94,8 +95,23 @@ func (a *archive) latestPath() string { return a.path } -func (a *archive) sigPath() string { - return filepath.Join(a.workDir, a.name+".sig") +// TODO: remove once we no longer ship go1.26. +// legacySigNeeded reports whether this archive needs a legacy .sig file +// in addition to the .asc file, for backward compatibility with go1.26 and earlier. +func (a *archive) legacySigNeeded() bool { + // Archive names look like "go1.27.linux-amd64.tar.gz" or "go1.26.3.src.tar.gz". + if after, ok := strings.CutPrefix(a.name, "go1."); ok { + if dot := strings.IndexByte(after, '.'); dot > 0 { + if minor, err := strconv.Atoi(after[:dot]); err == nil && minor <= 26 { + return true + } + } + } + return false +} + +func (a *archive) ascPath() string { + return filepath.Join(a.workDir, a.name+".asc") } func (a *archive) macHardenPackPath() string { @@ -428,18 +444,18 @@ func (a *archive) prepareArchiveSignatures(ctx context.Context) ([]*fileToSign, if err := ctx.Err(); err != nil { return nil, err } - // Copy the archive file to have .sig suffix, e.g. "tar.gz" to "tar.gz.sig". The signing - // process sends the "tar.gz.sig" file to get a signature, then replaces the "tar.gz.sig" - // file's content in-place with the result. We need to preemptively make a renamed copy of the - // file so we end up with both the original file and sig on the machine. - log.Printf("Copying file for signature generation: %q -> %q", a.latestPath(), a.sigPath()) - if err := copyFile(a.sigPath(), a.latestPath()); err != nil { + // Copy the archive file with an ".asc" suffix. The signing process sends this file to get a + // signature, then replaces its content in-place with the result. We need to preemptively make + // a renamed copy of the file so we end up with both the original file and signature on the + // machine. + log.Printf("Copying file for signature generation: %q -> %q", a.latestPath(), a.ascPath()) + if err := copyFile(a.ascPath(), a.latestPath()); err != nil { return nil, err } return []*fileToSign{ { originalPath: a.path, - fullPath: a.sigPath(), + fullPath: a.ascPath(), authenticode: "LinuxSignManagedLanguageCompiler", }, }, nil @@ -458,9 +474,15 @@ func (a *archive) copyToDestination(ctx context.Context) error { if err := copyFile(filepath.Join(*destinationDir, a.name), a.latestPath()); err != nil { return err } - if err := copyFile(filepath.Join(*destinationDir, a.name+".sig"), a.sigPath()); err != nil { + if err := copyFile(filepath.Join(*destinationDir, a.name+".asc"), a.ascPath()); err != nil { return err } + // For go1.26 and earlier, also produce a .sig file for backward compatibility. + if a.legacySigNeeded() { + if err := copyFile(filepath.Join(*destinationDir, a.name+".sig"), a.ascPath()); err != nil { + return err + } + } return nil } diff --git a/eng/_util/cmd/sign/sign.go b/eng/_util/cmd/sign/sign.go index c0f5332dfe5..1e4b05360c2 100644 --- a/eng/_util/cmd/sign/sign.go +++ b/eng/_util/cmd/sign/sign.go @@ -253,7 +253,7 @@ func sign(ctx context.Context, step string, files []*fileToSign) error { if *signType == "test" { log.Printf("Testing signing: skipping MicroBuild tooling.") for _, f := range files { - if strings.HasSuffix(f.fullPath, ".sig") { + if strings.HasSuffix(f.fullPath, ".sig") || strings.HasSuffix(f.fullPath, ".asc") { log.Printf("Replacing file with placeholder content to reduce size and simulate signature: %q", f.fullPath) // Get a checksum to make the file content unique. Otherwise, // publishing rejects the repeated file content. diff --git a/eng/_util/cmd/updatelinktable/updatelinktable.go b/eng/_util/cmd/updatelinktable/updatelinktable.go index c5b7bf837fe..dd92cc653c9 100644 --- a/eng/_util/cmd/updatelinktable/updatelinktable.go +++ b/eng/_util/cmd/updatelinktable/updatelinktable.go @@ -135,7 +135,7 @@ func filename(version, platform, ext string) string { const ( checksumSuffix = ".sha256" checksumMsg = "Checksum (SHA256)" - signatureSuffix = ".sig" + signatureSuffix = ".asc" signatureMsg = "Signature1" ) From f4530871d01f51ac5343cdb310e23fe03fde3a37 Mon Sep 17 00:00:00 2001 From: George Adams Date: Thu, 4 Jun 2026 15:45:02 +0100 Subject: [PATCH 2/2] fix linter --- eng/_util/cmd/sign/archive.go | 1 - 1 file changed, 1 deletion(-) diff --git a/eng/_util/cmd/sign/archive.go b/eng/_util/cmd/sign/archive.go index 1da9dc52b09..7ae58117ee7 100644 --- a/eng/_util/cmd/sign/archive.go +++ b/eng/_util/cmd/sign/archive.go @@ -95,7 +95,6 @@ func (a *archive) latestPath() string { return a.path } -// TODO: remove once we no longer ship go1.26. // legacySigNeeded reports whether this archive needs a legacy .sig file // in addition to the .asc file, for backward compatibility with go1.26 and earlier. func (a *archive) legacySigNeeded() bool {